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 6f112c69 feat(java,info): refactor yaml saver api (#763)
6f112c69 is described below
commit 6f112c69fef71bec0483ab0e5142e18f1165d1ea
Author: Xiaokang Yang <[email protected]>
AuthorDate: Sun Sep 28 11:24:21 2025 +0800
feat(java,info): refactor yaml saver api (#763)
* refactor saver
* format
* update
* update doc
* add test case
* update docs
* update
* fix import
* update saver method and add test
* fix
---
docs/libraries/java/info/getting-started.md | 60 ++++
.../java/org/apache/graphar/info/EdgeInfo.java | 7 +
.../java/org/apache/graphar/info/GraphInfo.java | 62 +++++
.../java/org/apache/graphar/info/VertexInfo.java | 7 +
.../graphar/info/loader/BaseGraphInfoLoader.java | 18 +-
.../graphar/info/loader/ReaderGraphInfoLoader.java | 4 +-
.../graphar/info/loader/StreamGraphInfoLoader.java | 8 +-
.../graphar/info/loader/StringGraphInfoLoader.java | 4 +-
.../graphar/info/saver/BaseGraphInfoSaver.java | 62 +++++
.../saver/{GraphSaver.java => GraphInfoSaver.java} | 12 +-
.../graphar/info/saver/LocalYamlGraphSaver.java | 85 ------
.../impl/LocalFileSystemYamlGraphSaver.java} | 27 +-
.../org/apache/graphar/info/type/FileType.java | 13 +
.../org/apache/graphar/info/yaml/GraphYaml.java | 25 +-
.../apache/graphar/info/BaseFileSystemTest.java | 2 +-
.../apache/graphar/info/GraphInfoSaverTest.java | 210 ++++++++++++++
.../org/apache/graphar/info/GraphInfoUriTest.java | 14 +-
.../org/apache/graphar/info/GraphSaverTest.java | 82 ------
.../org/apache/graphar/info/TestDataFactory.java | 12 +-
.../java/org/apache/graphar/info/TestUtil.java | 35 +++
.../apache/graphar/info/TestVerificationUtils.java | 301 +++++++++++++++++++++
21 files changed, 841 insertions(+), 209 deletions(-)
diff --git a/docs/libraries/java/info/getting-started.md
b/docs/libraries/java/info/getting-started.md
index 27e88e5d..fb110e16 100644
--- a/docs/libraries/java/info/getting-started.md
+++ b/docs/libraries/java/info/getting-started.md
@@ -96,6 +96,66 @@ MyStringGraphInfoLoader customLoader = new
MyStringGraphInfoLoader();
GraphInfo graphInfo =
customLoader.loadGraphInfo(URI.create("db://mydatabase/graphs/graph1/graph.yml"));
```
+### Save Graph Info
+
+The java-info module also provides functionality to save graph metadata to
YAML files using the `GraphSaver` interface. Here's an example of how to use it:
+
+```java
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.saver.GraphInfoSaver;
+import org.apache.graphar.info.saver.impl.LocalFileSystemYamlGraphSaver;
+import java.net.URI;
+
+// Create or obtain a GraphInfo object
+GraphInfo graphInfo = createOrLoadGraphInfo(); // your method to create or
load GraphInfo
+
+// Create a GraphSaver instance
+GraphInfoSaver graphSaver = new LocalFileSystemYamlGraphSaver();
+
+// Save the graph info to a directory
+String savePath = "/path/to/save/directory";
+try {
+ graphSaver.save(URI.create(savePath), graphInfo);
+ System.out.println("Graph info saved successfully to " + savePath);
+} catch (IOException e) {
+ System.err.println("Failed to save graph info: " + e.getMessage());
+ e.printStackTrace();
+}
+```
+
+This will save the graph metadata as a set of YAML files:
+- One main graph YAML file (e.g., `graph-name.graph.yaml`)
+- One YAML file for each vertex type (e.g., `person.vertex.yaml`)
+- One YAML file for each edge type (e.g., `person_knows_person.edge.yaml`)
+
+Alternatively, you can use the dump method to convert graph info to a string
and store it anywhere:
+
+```java
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.VertexInfo;
+import java.net.URI;
+
+// Create or obtain a GraphInfo object
+GraphInfo graphInfo = createOrLoadGraphInfo(); // your method to create or
load GraphInfo
+
+// Set custom storage URIs for vertex and edge info files
+for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
+ graphInfo.setStoreUri(vertexInfo, URI.create("db://path/vertex/" +
vertexInfo.getType() + ".vertex.yaml"));
+}
+
+for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
+ graphInfo.setStoreUri(edgeInfo, URI.create("db://path/edge/" +
edgeInfo.getConcat() + ".edge.yaml"));
+}
+
+// Convert graph info to YAML string
+String graphYamlString = graphInfo.dump();
+
+// Now you can store the YAML string anywhere you want
+// For example, save to a database, send over network, etc.
+saveYamlStringToDatabase(graphYamlString);
+```
+
### Building
To build the graphar-info module, you need:
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 57de3c44..cd18c16d 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,6 +19,7 @@
package org.apache.graphar.info;
+import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
@@ -494,6 +495,12 @@ public class EdgeInfo {
return getAdjacentListUri(adjListType).resolve("edge_count" +
vertexChunkIndex);
}
+ public void dump(Writer output) {
+ Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
+ EdgeYaml edgeYaml = new EdgeYaml(this);
+ yaml.dump(edgeYaml, output);
+ }
+
public String dump() {
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
EdgeYaml edgeYaml = new EdgeYaml(this);
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 c67a5428..e0ed2bfa 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,7 +19,10 @@
package org.apache.graphar.info;
+import java.io.Writer;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -37,6 +40,23 @@ public class GraphInfo {
private final Map<String, VertexInfo> vertexType2VertexInfo;
private final Map<String, EdgeInfo> edgeConcat2EdgeInfo;
private final VersionInfo version;
+ private final Map<String, URI> types2StoreUri;
+
+ public GraphInfo(
+ String name,
+ Map<URI, VertexInfo> vertexInfos,
+ Map<URI, EdgeInfo> edgeInfos,
+ URI uri,
+ String version) {
+ this(
+ name,
+ new ArrayList<>(vertexInfos.values()),
+ new ArrayList<>(edgeInfos.values()),
+ uri,
+ version);
+ vertexInfos.forEach((key, value) -> types2StoreUri.put(value.getType()
+ ".vertex", key));
+ edgeInfos.forEach((key, value) -> types2StoreUri.put(value.getConcat()
+ ".edge", key));
+ }
public GraphInfo(
String name,
@@ -68,6 +88,7 @@ public class GraphInfo {
.collect(
Collectors.toUnmodifiableMap(
EdgeInfo::getConcat,
Function.identity()));
+ this.types2StoreUri = new HashMap<>();
}
private GraphInfo(
@@ -103,6 +124,19 @@ public class GraphInfo {
this.version = version;
this.vertexType2VertexInfo = vertexType2VertexInfo;
this.edgeConcat2EdgeInfo = edgeConcat2EdgeInfo;
+ this.types2StoreUri = new HashMap<>();
+ }
+
+ public void dump(URI storeUri, Writer output) {
+ Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
+ GraphYaml graphYaml = new GraphYaml(storeUri, this);
+ yaml.dump(graphYaml, output);
+ }
+
+ public String dump(URI storeUri) {
+ Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
+ GraphYaml graphYaml = new GraphYaml(storeUri, this);
+ return yaml.dump(graphYaml);
}
public String dump() {
@@ -212,6 +246,34 @@ public class GraphInfo {
return version;
}
+ public void setStoreUri(VertexInfo vertexInfo, URI storeUri) {
+ this.types2StoreUri.put(vertexInfo.getType() + ".vertex", storeUri);
+ }
+
+ public void setStoreUri(EdgeInfo edgeInfo, URI storeUri) {
+ this.types2StoreUri.put(edgeInfo.getConcat() + ".edge", storeUri);
+ }
+
+ public URI getStoreUri(VertexInfo vertexInfo) {
+ String type = vertexInfo.getType() + ".vertex";
+ if (types2StoreUri.containsKey(type)) {
+ return types2StoreUri.get(type);
+ }
+ return URI.create(type + ".yaml");
+ }
+
+ public URI getStoreUri(EdgeInfo edgeInfo) {
+ String type = edgeInfo.getConcat() + ".edge";
+ if (types2StoreUri.containsKey(type)) {
+ return types2StoreUri.get(type);
+ }
+ return URI.create(type + ".yaml");
+ }
+
+ public Map<String, URI> getTypes2Uri() {
+ return types2StoreUri;
+ }
+
public boolean isValidated() {
// Check if name is not empty and base URI is not null
if (name == null || name.isEmpty() || baseUri == null) {
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 94123a05..b4a14c5e 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,6 +19,7 @@
package org.apache.graphar.info;
+import java.io.Writer;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
@@ -122,6 +123,12 @@ public class VertexInfo {
return getBaseUri().resolve("vertex_count");
}
+ public void dump(Writer output) {
+ Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
+ VertexYaml vertexYaml = new VertexYaml(this);
+ yaml.dump(vertexYaml, output);
+ }
+
public String dump() {
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
VertexYaml vertexYaml = new VertexYaml(this);
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
index 77b74f8b..50463373 100644
---
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
@@ -21,8 +21,8 @@ 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.Map;
+import java.util.TreeMap;
import java.util.stream.Collectors;
import org.apache.graphar.info.EdgeInfo;
import org.apache.graphar.info.GraphInfo;
@@ -41,7 +41,7 @@ public abstract class BaseGraphInfoLoader implements
GraphInfoLoader {
public abstract EdgeInfo loadEdgeInfo(URI edgeYamlUri) throws IOException;
- public GraphInfo buildGraphInfoFromGraphYaml(URI baseUri, GraphYaml
graphYaml)
+ protected GraphInfo buildGraphInfoFromGraphYaml(URI baseUri, GraphYaml
graphYaml)
throws IOException {
URI defaultBaseUri = baseUri.resolve(".");
@@ -50,16 +50,16 @@ public abstract class BaseGraphInfoLoader implements
GraphInfoLoader {
}
// load vertices
- List<VertexInfo> vertexInfos = new
ArrayList<>(graphYaml.getVertices().size());
+ Map<URI, VertexInfo> vertexInfos = new TreeMap<>();
for (String vertexYamlPath : graphYaml.getVertices()) {
URI vertexInfoUri = baseUri.resolve(vertexYamlPath);
- vertexInfos.add(loadVertexInfo(vertexInfoUri));
+ vertexInfos.put(vertexInfoUri, loadVertexInfo(vertexInfoUri));
}
// load edges
- List<EdgeInfo> edgeInfos = new
ArrayList<>(graphYaml.getEdges().size());
+ Map<URI, EdgeInfo> edgeInfos = new TreeMap<>();
for (String edgeYamlPath : graphYaml.getEdges()) {
URI edgeInfoUri = baseUri.resolve(edgeYamlPath);
- edgeInfos.add(loadEdgeInfo(edgeInfoUri));
+ edgeInfos.put(edgeInfoUri, loadEdgeInfo(edgeInfoUri));
}
return new GraphInfo(
graphYaml.getName(),
@@ -69,7 +69,7 @@ public abstract class BaseGraphInfoLoader implements
GraphInfoLoader {
graphYaml.getVersion());
}
- public VertexInfo buildVertexInfoFromGraphYaml(VertexYaml vertexYaml) {
+ protected VertexInfo buildVertexInfoFromVertexYaml(VertexYaml vertexYaml) {
return new VertexInfo(
vertexYaml.getType(),
vertexYaml.getChunk_size(),
@@ -80,7 +80,7 @@ public abstract class BaseGraphInfoLoader implements
GraphInfoLoader {
vertexYaml.getVersion());
}
- public EdgeInfo buildEdgeInfoFromGraphYaml(EdgeYaml edgeYaml) {
+ protected EdgeInfo buildEdgeInfoFromEdgeYaml(EdgeYaml edgeYaml) {
return new EdgeInfo(
edgeYaml.getSrc_type(),
edgeYaml.getEdge_type(),
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
index f83b826b..c6af59a4 100644
---
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
@@ -49,7 +49,7 @@ public abstract class ReaderGraphInfoLoader extends
BaseGraphInfoLoader {
Reader yaml = readYaml(vertexYamlUri);
Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new
LoaderOptions()));
VertexYaml vertexYaml = vertexYamlLoader.load(yaml);
- return buildVertexInfoFromGraphYaml(vertexYaml);
+ return buildVertexInfoFromVertexYaml(vertexYaml);
}
@Override
@@ -57,6 +57,6 @@ public abstract class ReaderGraphInfoLoader extends
BaseGraphInfoLoader {
Reader yaml = readYaml(edgeYamlUri);
Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new
LoaderOptions()));
EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
- return buildEdgeInfoFromGraphYaml(edgeYaml);
+ return buildEdgeInfoFromEdgeYaml(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
index 5292c622..65dc567f 100644
---
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
@@ -48,9 +48,9 @@ public abstract class StreamGraphInfoLoader extends
BaseGraphInfoLoader {
@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);
+ Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new
LoaderOptions()));
+ VertexYaml vertexYaml = vertexYamlLoader.load(yaml);
+ return buildVertexInfoFromVertexYaml(vertexYaml);
}
@Override
@@ -58,6 +58,6 @@ public abstract class StreamGraphInfoLoader extends
BaseGraphInfoLoader {
InputStream yaml = readYaml(edgeYamlUri);
Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new
LoaderOptions()));
EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
- return buildEdgeInfoFromGraphYaml(edgeYaml);
+ return buildEdgeInfoFromEdgeYaml(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
index cc82ab69..427e8e90 100644
---
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
@@ -48,7 +48,7 @@ public abstract class StringGraphInfoLoader extends
BaseGraphInfoLoader {
String yaml = readYaml(vertexYamlUri);
Yaml vertexYamlLoader = new Yaml(new Constructor(VertexYaml.class, new
LoaderOptions()));
VertexYaml vertexYaml = vertexYamlLoader.load(yaml);
- return buildVertexInfoFromGraphYaml(vertexYaml);
+ return buildVertexInfoFromVertexYaml(vertexYaml);
}
@Override
@@ -56,6 +56,6 @@ public abstract class StringGraphInfoLoader extends
BaseGraphInfoLoader {
String yaml = readYaml(edgeYamlUri);
Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new
LoaderOptions()));
EdgeYaml edgeYaml = edgeYamlLoader.load(yaml);
- return buildEdgeInfoFromGraphYaml(edgeYaml);
+ return buildEdgeInfoFromEdgeYaml(edgeYaml);
}
}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/BaseGraphInfoSaver.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/BaseGraphInfoSaver.java
new file mode 100644
index 00000000..a59bdcc7
--- /dev/null
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/BaseGraphInfoSaver.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.saver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import org.apache.graphar.info.EdgeInfo;
+import org.apache.graphar.info.GraphInfo;
+import org.apache.graphar.info.VertexInfo;
+
+public abstract class BaseGraphInfoSaver implements GraphInfoSaver {
+
+ public abstract Writer writeYaml(URI uri) throws IOException;
+
+ @Override
+ public void save(URI graphInfoUri, GraphInfo graphInfo) throws IOException
{
+ Writer writer = writeYaml(graphInfoUri);
+ graphInfo.dump(graphInfoUri, writer);
+ writer.close();
+
+ for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
+ URI saveUri =
graphInfoUri.resolve(graphInfo.getStoreUri(vertexInfo));
+ save(saveUri, vertexInfo);
+ }
+ for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
+ URI saveUri =
graphInfoUri.resolve(graphInfo.getStoreUri(edgeInfo));
+ save(saveUri, edgeInfo);
+ }
+ }
+
+ @Override
+ public void save(URI vertexInfoUri, VertexInfo vertexInfo) throws
IOException {
+ Writer vertexWriter = writeYaml(vertexInfoUri);
+ vertexInfo.dump(vertexWriter);
+ vertexWriter.close();
+ }
+
+ @Override
+ public void save(URI edgeInfoUri, EdgeInfo edgeInfo) throws IOException {
+ Writer edgeWriter = writeYaml(edgeInfoUri);
+ edgeInfo.dump(edgeWriter);
+ edgeWriter.close();
+ }
+}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphInfoSaver.java
similarity index 71%
rename from
maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
rename to
maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphInfoSaver.java
index 5ee1d916..084409e6 100644
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphSaver.java
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/GraphInfoSaver.java
@@ -20,9 +20,15 @@
package org.apache.graphar.info.saver;
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;
-@FunctionalInterface
-public interface GraphSaver {
- void save(String path, GraphInfo graphInfo) throws IOException;
+public interface GraphInfoSaver {
+ void save(URI graphInfoUri, GraphInfo graphInfo) throws IOException;
+
+ void save(URI vertexInfoUri, VertexInfo vertexInfo) throws IOException;
+
+ void save(URI edgeInfoUri, EdgeInfo edgeInfo) throws IOException;
}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
deleted file mode 100644
index 7038fbb3..00000000
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/saver/LocalYamlGraphSaver.java
+++ /dev/null
@@ -1,85 +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.saver;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.apache.graphar.info.EdgeInfo;
-import org.apache.graphar.info.GraphInfo;
-import org.apache.graphar.info.VertexInfo;
-
-public class LocalYamlGraphSaver implements GraphSaver {
-
- @Override
- public void save(String path, GraphInfo graphInfo) throws IOException {
- final Path outputPath =
- FileSystems.getDefault()
- .getPath(
- path
- +
FileSystems.getDefault().getSeparator()
- + graphInfo.getName()
- + ".graph.yaml");
- Files.createDirectories(outputPath.getParent());
- Files.createFile(outputPath);
- final BufferedWriter writer = Files.newBufferedWriter(outputPath);
- writer.write(graphInfo.dump());
- writer.close();
-
- for (VertexInfo vertexInfo : graphInfo.getVertexInfos()) {
- saveVertex(path, vertexInfo);
- }
- for (EdgeInfo edgeInfo : graphInfo.getEdgeInfos()) {
- saveEdge(path, edgeInfo);
- }
- }
-
- private void saveVertex(String path, VertexInfo vertexInfo) throws
IOException {
- final Path outputPath =
- FileSystems.getDefault()
- .getPath(
- path
- +
FileSystems.getDefault().getSeparator()
- + vertexInfo.getType()
- + ".vertex.yaml");
- Files.createDirectories(outputPath.getParent());
- Files.createFile(outputPath);
- final BufferedWriter writer = Files.newBufferedWriter(outputPath);
- writer.write(vertexInfo.dump());
- writer.close();
- }
-
- private void saveEdge(String path, EdgeInfo edgeInfo) throws IOException {
- final Path outputPath =
- FileSystems.getDefault()
- .getPath(
- path
- +
FileSystems.getDefault().getSeparator()
- + edgeInfo.getConcat()
- + ".edge.yaml");
- Files.createDirectories(outputPath.getParent());
- Files.createFile(outputPath);
- final BufferedWriter writer = Files.newBufferedWriter(outputPath);
- writer.write(edgeInfo.dump());
- writer.close();
- }
-}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/impl/LocalFileSystemYamlGraphSaver.java
similarity index 50%
rename from
maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
rename to
maven-projects/info/src/main/java/org/apache/graphar/info/saver/impl/LocalFileSystemYamlGraphSaver.java
index b21238c1..4c49c3af 100644
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/loader/GraphLoader.java
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/saver/impl/LocalFileSystemYamlGraphSaver.java
@@ -17,12 +17,29 @@
* under the License.
*/
-package org.apache.graphar.info.loader;
+package org.apache.graphar.info.saver.impl;
import java.io.IOException;
-import org.apache.graphar.info.GraphInfo;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import org.apache.graphar.info.saver.BaseGraphInfoSaver;
-@FunctionalInterface
-public interface GraphLoader {
- public GraphInfo load(String graphYamlPath) throws IOException;
+public class LocalFileSystemYamlGraphSaver extends BaseGraphInfoSaver {
+
+ public Writer writeYaml(URI uri) throws IOException {
+ Path outputPath = FileSystems.getDefault().getPath(uri.toString());
+ Path parentDir = outputPath.getParent();
+ if (parentDir != null) {
+ Files.createDirectories(parentDir);
+ }
+ return Files.newBufferedWriter(
+ outputPath,
+ StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING,
+ StandardOpenOption.WRITE);
+ }
}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
index b45038b8..09e5bb19 100644
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/FileType.java
@@ -24,6 +24,19 @@ public enum FileType {
PARQUET,
ORC;
+ public String toString() {
+ switch (this) {
+ case CSV:
+ return "csv";
+ case PARQUET:
+ return "parquet";
+ case ORC:
+ return "orc";
+ default:
+ throw new IllegalArgumentException("Unknown file type: " +
this);
+ }
+ }
+
public static FileType fromString(String fileType) {
if (fileType == null) {
return null;
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
index bf665dcd..f5353967 100644
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/GraphYaml.java
@@ -19,6 +19,7 @@
package org.apache.graphar.info.yaml;
+import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -77,6 +78,10 @@ public class GraphYaml {
}
public GraphYaml(GraphInfo graphInfo) {
+ this(null, graphInfo);
+ }
+
+ public GraphYaml(URI graphInfoStoreUri, GraphInfo graphInfo) {
this.name = graphInfo.getName();
this.prefix = graphInfo.getPrefix();
this.version =
@@ -86,11 +91,27 @@ public class GraphYaml {
.orElse(null);
this.vertices =
graphInfo.getVertexInfos().stream()
- .map(vertexInfo -> vertexInfo.getType() +
".vertex.yaml")
+ .map(
+ vertexInfo -> {
+ URI storeUri =
graphInfo.getStoreUri(vertexInfo);
+ if (graphInfoStoreUri != null) {
+ storeUri =
+
graphInfoStoreUri.resolve(".").relativize(storeUri);
+ }
+ return storeUri.toString();
+ })
.collect(Collectors.toList());
this.edges =
graphInfo.getEdgeInfos().stream()
- .map(edgeInfo -> edgeInfo.getConcat() + ".edge.yaml")
+ .map(
+ edgeInfo -> {
+ URI storeUri =
graphInfo.getStoreUri(edgeInfo);
+ if (graphInfoStoreUri != null) {
+ storeUri =
+
graphInfoStoreUri.resolve(".").relativize(storeUri);
+ }
+ return storeUri.toString();
+ })
.collect(Collectors.toList());
this.version =
Optional.of(graphInfo)
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/BaseFileSystemTest.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/BaseFileSystemTest.java
index 37c39230..84c46389 100644
---
a/maven-projects/info/src/test/java/org/apache/graphar/info/BaseFileSystemTest.java
+++
b/maven-projects/info/src/test/java/org/apache/graphar/info/BaseFileSystemTest.java
@@ -88,7 +88,7 @@ public abstract class BaseFileSystemTest {
* content before creating the directory.
*/
protected String createCleanTestDirectory(String subdirectoryName) {
- String testDir = TEST_OUTPUT_DIR + "/" + subdirectoryName;
+ String testDir = TEST_OUTPUT_DIR + subdirectoryName;
cleanupDirectory(testDir);
try {
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoSaverTest.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoSaverTest.java
new file mode 100644
index 00000000..0c37f96e
--- /dev/null
+++
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphInfoSaverTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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 java.nio.file.FileSystems;
+import java.util.ArrayList;
+import java.util.List;
+import
org.apache.graphar.info.loader.impl.LocalFileSystemStringGraphInfoLoader;
+import org.apache.graphar.info.saver.GraphInfoSaver;
+import org.apache.graphar.info.saver.impl.LocalFileSystemYamlGraphSaver;
+import org.apache.graphar.info.yaml.EdgeYaml;
+import org.apache.graphar.info.yaml.GraphYaml;
+import org.apache.graphar.info.yaml.VertexYaml;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public class GraphInfoSaverTest extends BaseFileSystemTest {
+
+ private String testSaveDirectory;
+ private GraphInfoSaver graphInfoSaver;
+ private GraphInfo testGraphInfo;
+
+ @Before
+ public void setUp() {
+ verifyTestPrerequisites();
+ testSaveDirectory = createCleanTestDirectory("ldbc_sample");
+ graphInfoSaver = new LocalFileSystemYamlGraphSaver();
+ testGraphInfo = TestDataFactory.createSampleGraphInfo();
+ }
+
+ @After
+ public void tearDown() {
+ // Test data will be preserved for debugging - cleanup happens before
next test run
+ System.out.println("Test data saved in: " + testSaveDirectory);
+ }
+
+ @Test
+ public void testDump() {
+ List<VertexInfo> vertexInfos = new ArrayList<>();
+ for (VertexInfo vertexInfo : testGraphInfo.getVertexInfos()) {
+ String vertexYamlString = vertexInfo.dump();
+ Yaml vertexYamlLoader =
+ new Yaml(new Constructor(VertexYaml.class, new
LoaderOptions()));
+ VertexYaml vertexYaml = vertexYamlLoader.load(vertexYamlString);
+ VertexInfo vertexInfoFromYaml =
TestUtil.buildVertexInfoFromYaml(vertexYaml);
+ vertexInfos.add(vertexInfoFromYaml);
+ }
+ List<EdgeInfo> edgeInfos = new ArrayList<>();
+ for (EdgeInfo edgeInfo : testGraphInfo.getEdgeInfos()) {
+ String edgeYamlString = edgeInfo.dump();
+ Yaml edgeYamlLoader = new Yaml(new Constructor(EdgeYaml.class, new
LoaderOptions()));
+ EdgeYaml EdgeYaml = edgeYamlLoader.load(edgeYamlString);
+ EdgeInfo EdgeInfoFromYaml =
TestUtil.buildEdgeInfoFromYaml(EdgeYaml);
+ edgeInfos.add(EdgeInfoFromYaml);
+ }
+ String testGraphInfoString = testGraphInfo.dump();
+ Yaml GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new
LoaderOptions()));
+ GraphYaml graphYaml = GraphYamlLoader.load(testGraphInfoString);
+ GraphInfo graphInfoFromYaml =
+ new GraphInfo(
+ graphYaml.getName(),
+ vertexInfos,
+ edgeInfos,
+ graphYaml.getPrefix(),
+ graphYaml.getVersion());
+ Assert.assertTrue(TestVerificationUtils.equalsGraphInfo(testGraphInfo,
graphInfoFromYaml));
+ }
+
+ @Test
+ public void testDumpWithBaseUri() {
+ GraphInfo dumpTestGraphInfo = TestDataFactory.createSampleGraphInfo();
+ dumpTestGraphInfo.setStoreUri(
+ dumpTestGraphInfo.getVertexInfos().get(0),
+ URI.create("/tmp/verticesInfos/personInfo.vertex.yaml"));
+ String dumpTestGraphInfoString =
dumpTestGraphInfo.dump(URI.create("/tmp/GraphInfos/"));
+ Yaml GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new
LoaderOptions()));
+ GraphYaml graphYaml = GraphYamlLoader.load(dumpTestGraphInfoString);
+ Assert.assertEquals(
+ "/tmp/verticesInfos/personInfo.vertex.yaml",
graphYaml.getVertices().get(0));
+ dumpTestGraphInfo.setStoreUri(
+ dumpTestGraphInfo.getVertexInfos().get(0),
+ URI.create("/tmp/verticesInfos/personInfo.vertex.yaml"));
+ dumpTestGraphInfoString =
dumpTestGraphInfo.dump(URI.create("/tmp/verticesInfos/"));
+ GraphYamlLoader = new Yaml(new Constructor(GraphYaml.class, new
LoaderOptions()));
+ graphYaml = GraphYamlLoader.load(dumpTestGraphInfoString);
+ Assert.assertEquals("personInfo.vertex.yaml",
graphYaml.getVertices().get(0));
+ }
+
+ @Test
+ public void testSave() {
+ try {
+ URI graphInfoUri =
+ URI.create(
+ testSaveDirectory
+ + FileSystems.getDefault().getSeparator()
+ + testGraphInfo.getName()
+ + ".graph.yaml");
+ graphInfoSaver.save(graphInfoUri, testGraphInfo);
+ TestVerificationUtils.verifyGraphInfoFilesSaved(testSaveDirectory,
testGraphInfo);
+ LocalFileSystemStringGraphInfoLoader graphInfoLoader =
+ new LocalFileSystemStringGraphInfoLoader();
+ GraphInfo graphInfo = graphInfoLoader.loadGraphInfo(graphInfoUri);
+ TestVerificationUtils.equalsGraphInfo(testGraphInfo, graphInfo);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to save graph info", e);
+ }
+ }
+
+ @Test
+ public void testSaveMinimalGraph() {
+ GraphInfo minimalGraph = TestDataFactory.createMinimalGraphInfo();
+ try {
+ URI graphInfoUri =
+ URI.create(
+ testSaveDirectory
+ + FileSystems.getDefault().getSeparator()
+ + minimalGraph.getName()
+ + ".graph.yaml");
+ graphInfoSaver.save(graphInfoUri, minimalGraph);
+ TestVerificationUtils.verifyGraphFileExists(testSaveDirectory,
minimalGraph);
+ TestVerificationUtils.verifyVertexFilesExist(testSaveDirectory,
minimalGraph);
+ LocalFileSystemStringGraphInfoLoader graphInfoLoader =
+ new LocalFileSystemStringGraphInfoLoader();
+ GraphInfo graphInfo = graphInfoLoader.loadGraphInfo(graphInfoUri);
+ TestVerificationUtils.equalsGraphInfo(minimalGraph, graphInfo);
+ // No edge files expected for minimal graph
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to save minimal graph info", e);
+ }
+ }
+
+ @Test
+ public void testSaveGraph2DiffPath() {
+ for (VertexInfo vertexInfo : testGraphInfo.getVertexInfos()) {
+ testGraphInfo.setStoreUri(
+ vertexInfo,
+ URI.create(testSaveDirectory + "/test_vertices/")
+ .resolve(testGraphInfo.getStoreUri(vertexInfo)));
+ }
+
+ for (EdgeInfo edgeInfo : testGraphInfo.getEdgeInfos()) {
+ testGraphInfo.setStoreUri(
+ edgeInfo,
+ URI.create(testSaveDirectory + "/test_edges/")
+ .resolve(testGraphInfo.getStoreUri(edgeInfo)));
+ }
+ try {
+ URI graphInfoUri =
+ URI.create(
+ testSaveDirectory
+ + FileSystems.getDefault().getSeparator()
+ + testGraphInfo.getName()
+ + ".graph.yaml");
+ graphInfoSaver.save(graphInfoUri, testGraphInfo);
+ TestVerificationUtils.verifyGraphFileExists(testSaveDirectory,
testGraphInfo);
+ TestVerificationUtils.verifyVertexFilesExist(
+ testSaveDirectory + "/test_vertices", testGraphInfo);
+ TestVerificationUtils.verifyEdgeFilesExist(
+ testSaveDirectory + "/test_edges", testGraphInfo);
+ // No edge files expected for minimal graph
+ LocalFileSystemStringGraphInfoLoader graphInfoLoader =
+ new LocalFileSystemStringGraphInfoLoader();
+ GraphInfo graphInfo = graphInfoLoader.loadGraphInfo(graphInfoUri);
+ TestVerificationUtils.equalsGraphInfo(testGraphInfo, graphInfo);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to save test graph info", e);
+ }
+ }
+
+ @Test
+ public void testSaveDirectoryCreation() {
+ String nestedDir = testSaveDirectory + "/nested/deep/directory";
+ try {
+ URI graphInfoUri =
+ URI.create(
+ nestedDir
+ + FileSystems.getDefault().getSeparator()
+ + testGraphInfo.getName()
+ + ".graph.yaml");
+ graphInfoSaver.save(graphInfoUri, testGraphInfo);
+ TestVerificationUtils.verifyDirectoryHasFiles(nestedDir);
+ TestVerificationUtils.verifyGraphInfoFilesSaved(nestedDir,
testGraphInfo);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to save to nested directory",
e);
+ }
+ }
+}
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
index 2607376f..78fb5616 100644
---
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
@@ -20,8 +20,6 @@
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;
@@ -35,8 +33,7 @@ public class GraphInfoUriTest {
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);
+ VertexInfo vertexInfo = TestUtil.buildVertexInfoFromYaml(vertexYaml);
Assert.assertEquals(URI.create("vertex/person/"),
vertexInfo.getBaseUri());
// absolute paths
Assert.assertEquals(
@@ -52,8 +49,7 @@ public class GraphInfoUriTest {
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);
+ VertexInfo vertexInfo = TestUtil.buildVertexInfoFromYaml(vertexYaml);
Assert.assertEquals(URI.create("s3://graphar/vertex/person/"),
vertexInfo.getBaseUri());
// absolute paths
Assert.assertEquals(
@@ -69,8 +65,7 @@ public class GraphInfoUriTest {
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);
+ VertexInfo vertexInfo = TestUtil.buildVertexInfoFromYaml(vertexYaml);
Assert.assertEquals(URI.create("hdfs://graphar/vertex/person/"),
vertexInfo.getBaseUri());
// absolute paths
Assert.assertEquals(
@@ -86,8 +81,7 @@ public class GraphInfoUriTest {
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);
+ VertexInfo vertexInfo = TestUtil.buildVertexInfoFromYaml(vertexYaml);
Assert.assertEquals(URI.create("file:///graphar/vertex/person/"),
vertexInfo.getBaseUri());
// absolute paths
Assert.assertEquals(
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java
deleted file mode 100644
index 928d6e70..00000000
---
a/maven-projects/info/src/test/java/org/apache/graphar/info/GraphSaverTest.java
+++ /dev/null
@@ -1,82 +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 org.apache.graphar.info.saver.GraphSaver;
-import org.apache.graphar.info.saver.LocalYamlGraphSaver;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class GraphSaverTest extends BaseFileSystemTest {
-
- private String testSaveDirectory;
- private GraphSaver graphSaver;
- private GraphInfo testGraphInfo;
-
- @Before
- public void setUp() {
- verifyTestPrerequisites();
- testSaveDirectory = createCleanTestDirectory("ldbc_sample");
- graphSaver = new LocalYamlGraphSaver();
- testGraphInfo = TestDataFactory.createSampleGraphInfo();
- }
-
- @After
- public void tearDown() {
- // Test data will be preserved for debugging - cleanup happens before
next test run
- System.out.println("Test data saved in: " + testSaveDirectory);
- }
-
- @Test
- public void testSave() {
- try {
- graphSaver.save(testSaveDirectory, testGraphInfo);
- TestVerificationUtils.verifyGraphInfoFilesSaved(testSaveDirectory,
testGraphInfo);
- } catch (Exception e) {
- throw new RuntimeException("Failed to save graph info", e);
- }
- }
-
- @Test
- public void testSaveMinimalGraph() {
- GraphInfo minimalGraph = TestDataFactory.createMinimalGraphInfo();
- try {
- graphSaver.save(testSaveDirectory, minimalGraph);
- TestVerificationUtils.verifyGraphFileExists(testSaveDirectory,
minimalGraph);
- TestVerificationUtils.verifyVertexFilesExist(testSaveDirectory,
minimalGraph);
- // No edge files expected for minimal graph
- } catch (Exception e) {
- throw new RuntimeException("Failed to save minimal graph info", e);
- }
- }
-
- @Test
- public void testSaveDirectoryCreation() {
- String nestedDir = testSaveDirectory + "/nested/deep/directory";
- try {
- graphSaver.save(nestedDir, testGraphInfo);
- TestVerificationUtils.verifyDirectoryHasFiles(nestedDir);
- TestVerificationUtils.verifyGraphInfoFilesSaved(nestedDir,
testGraphInfo);
- } catch (Exception e) {
- throw new RuntimeException("Failed to save to nested directory",
e);
- }
- }
-}
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/TestDataFactory.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestDataFactory.java
index 1c6cffd0..b2943488 100644
---
a/maven-projects/info/src/test/java/org/apache/graphar/info/TestDataFactory.java
+++
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestDataFactory.java
@@ -38,7 +38,11 @@ public class TestDataFactory {
VertexInfo personVertex = createPersonVertexInfo();
EdgeInfo knowsEdge = createKnowsEdgeInfo();
return new GraphInfo(
- "ldbc_sample", List.of(personVertex), List.of(knowsEdge), "",
"gar/v1");
+ "ldbc_sample",
+ List.of(personVertex),
+ List.of(knowsEdge),
+ "file:///test_path",
+ "gar/v1");
}
/** Creates a person vertex info for testing. */
@@ -48,11 +52,11 @@ public class TestDataFactory {
Property lastName = createProperty("lastName", DataType.STRING, false,
false);
Property gender = createProperty("gender", DataType.STRING, false,
true);
- PropertyGroup idGroup = createPropertyGroup(List.of(id), FileType.CSV,
"id/");
+ PropertyGroup idGroup = createPropertyGroup(List.of(id),
FileType.PARQUET, "id/");
PropertyGroup nameGroup =
createPropertyGroup(
List.of(firstName, lastName, gender),
- FileType.CSV,
+ FileType.ORC,
"firstName_lastName_gender/");
return new VertexInfo(
@@ -113,6 +117,6 @@ public class TestDataFactory {
Property id = createIdProperty();
PropertyGroup idGroup = createPropertyGroup(List.of(id), FileType.CSV,
"id/");
VertexInfo vertex = new VertexInfo("test", 100, List.of(idGroup),
"vertex/test/", "gar/v1");
- return new GraphInfo("test_graph", List.of(vertex), List.of(), "",
"gar/v1");
+ return new GraphInfo("test_graph", List.of(vertex), List.of(), "/tmp",
"gar/v1");
}
}
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 e1ebf6f6..880c6005 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
@@ -21,10 +21,15 @@ package org.apache.graphar.info;
import java.net.URI;
import java.util.List;
+import java.util.stream.Collectors;
import org.apache.graphar.info.loader.GraphInfoLoader;
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.info.yaml.AdjacentListYaml;
+import org.apache.graphar.info.yaml.EdgeYaml;
+import org.apache.graphar.info.yaml.PropertyGroupYaml;
+import org.apache.graphar.info.yaml.VertexYaml;
public class TestUtil {
private static String GAR_TEST_DATA = null;
@@ -51,6 +56,36 @@ public class TestUtil {
return URI.create(getLdbcSampleGraphPath());
}
+ public static VertexInfo buildVertexInfoFromYaml(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 static EdgeInfo buildEdgeInfoFromYaml(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()));
+ }
+
public static final AdjacentList orderedBySource =
new AdjacentList(AdjListType.ordered_by_source, FileType.CSV,
"ordered_by_source/");
public static final AdjacentList orderedByDest =
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/TestVerificationUtils.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestVerificationUtils.java
index c8c6bfdb..fe09e6e6 100644
---
a/maven-projects/info/src/test/java/org/apache/graphar/info/TestVerificationUtils.java
+++
b/maven-projects/info/src/test/java/org/apache/graphar/info/TestVerificationUtils.java
@@ -20,6 +20,9 @@
package org.apache.graphar.info;
import java.io.File;
+import java.util.List;
+import java.util.Map;
+import org.apache.graphar.info.type.AdjListType;
import org.junit.Assert;
/**
@@ -138,4 +141,302 @@ public class TestVerificationUtils {
Assert.assertNotNull("Directory should be readable: " + directoryPath,
files);
Assert.assertTrue("Directory should contain files: " + directoryPath,
files.length > 0);
}
+
+ /**
+ * Compares two GraphInfo objects for equality, including their VertexInfo
and EdgeInfo objects.
+ *
+ * @param expected the expected GraphInfo
+ * @param actual the actual GraphInfo
+ * @return true if both GraphInfo objects are equal, false otherwise
+ */
+ public static boolean equalsGraphInfo(GraphInfo expected, GraphInfo
actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals("GraphInfo name mismatch", expected.getName(),
actual.getName());
+ Assert.assertEquals(
+ "GraphInfo baseUri mismatch", expected.getBaseUri(),
actual.getBaseUri());
+ Assert.assertEquals(
+ "GraphInfo version mismatch",
+ expected.getVersion().toString(),
+ actual.getVersion().toString());
+ Assert.assertTrue(
+ "VertexInfo list mismatch",
+ equalsVertexInfoList(expected.getVertexInfos(),
actual.getVertexInfos()));
+ Assert.assertTrue(
+ "EdgeInfo list mismatch",
+ equalsEdgeInfoList(expected.getEdgeInfos(),
actual.getEdgeInfos()));
+ return true;
+ }
+
+ /**
+ * Compares two lists of VertexInfo objects for equality.
+ *
+ * @param expected the expected list of VertexInfo objects
+ * @param actual the actual list of VertexInfo objects
+ * @return true if both lists are equal, false otherwise
+ */
+ public static boolean equalsVertexInfoList(List<VertexInfo> expected,
List<VertexInfo> actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null || expected.size() !=
actual.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < expected.size(); i++) {
+ Assert.assertTrue(
+ "VertexInfo at index " + i + " mismatch",
+ equalsVertexInfo(expected.get(i), actual.get(i)));
+ }
+ return true;
+ }
+
+ /**
+ * Compares two lists of EdgeInfo objects for equality.
+ *
+ * @param expected the expected list of EdgeInfo objects
+ * @param actual the actual list of EdgeInfo objects
+ * @return true if both lists are equal, false otherwise
+ */
+ public static boolean equalsEdgeInfoList(List<EdgeInfo> expected,
List<EdgeInfo> actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null || expected.size() !=
actual.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < expected.size(); i++) {
+ Assert.assertTrue(
+ "EdgeInfo at index " + i + " mismatch",
+ equalsEdgeInfo(expected.get(i), actual.get(i)));
+ }
+ return true;
+ }
+
+ /**
+ * Compares two VertexInfo objects for equality.
+ *
+ * @param expected the expected VertexInfo
+ * @param actual the actual VertexInfo
+ * @return true if both VertexInfo objects are equal, false otherwise
+ */
+ public static boolean equalsVertexInfo(VertexInfo expected, VertexInfo
actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals("VertexInfo type mismatch", expected.getType(),
actual.getType());
+ Assert.assertEquals(
+ "VertexInfo chunk size mismatch", expected.getChunkSize(),
actual.getChunkSize());
+ Assert.assertEquals("VertexInfo prefix mismatch",
expected.getPrefix(), actual.getPrefix());
+ Assert.assertEquals(
+ "VertexInfo version mismatch",
+ expected.getVersion().toString(),
+ actual.getVersion().toString());
+ Assert.assertTrue(
+ "VertexInfo property groups mismatch",
+ equalsPropertyGroupList(expected.getPropertyGroups(),
actual.getPropertyGroups()));
+ return true;
+ }
+
+ /**
+ * Compares two EdgeInfo objects for equality.
+ *
+ * @param expected the expected EdgeInfo
+ * @param actual the actual EdgeInfo
+ * @return true if both EdgeInfo objects are equal, false otherwise
+ */
+ public static boolean equalsEdgeInfo(EdgeInfo expected, EdgeInfo actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals(
+ "EdgeInfo source type mismatch", expected.getSrcType(),
actual.getSrcType());
+ Assert.assertEquals(
+ "EdgeInfo edge type mismatch", expected.getEdgeType(),
actual.getEdgeType());
+ Assert.assertEquals(
+ "EdgeInfo destination type mismatch", expected.getDstType(),
actual.getDstType());
+ Assert.assertEquals(
+ "EdgeInfo chunk size mismatch", expected.getChunkSize(),
actual.getChunkSize());
+ Assert.assertEquals(
+ "EdgeInfo source chunk size mismatch",
+ expected.getSrcChunkSize(),
+ actual.getSrcChunkSize());
+ Assert.assertEquals(
+ "EdgeInfo destination chunk size mismatch",
+ expected.getDstChunkSize(),
+ actual.getDstChunkSize());
+ Assert.assertEquals(
+ "EdgeInfo directed mismatch", expected.isDirected(),
actual.isDirected());
+ Assert.assertEquals("EdgeInfo prefix mismatch", expected.getPrefix(),
actual.getPrefix());
+ Assert.assertEquals(
+ "EdgeInfo version mismatch",
+ expected.getVersion().toString(),
+ actual.getVersion().toString());
+ Assert.assertTrue(
+ "EdgeInfo adjacent lists mismatch",
+ equalsAdjacentListMap(expected.getAdjacentLists(),
actual.getAdjacentLists()));
+ Assert.assertTrue(
+ "EdgeInfo property groups mismatch",
+ equalsPropertyGroupList(expected.getPropertyGroups(),
actual.getPropertyGroups()));
+ return true;
+ }
+
+ /**
+ * Compares two PropertyGroups objects for equality.
+ *
+ * @param expected the expected list of PropertyGroup objects
+ * @param actual the actual list of PropertyGroup objects
+ * @return true if both lists are equal, false otherwise
+ */
+ private static boolean equalsPropertyGroupList(
+ List<PropertyGroup> expected, List<PropertyGroup> actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null || expected.size() !=
actual.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < expected.size(); i++) {
+ Assert.assertTrue(
+ "PropertyGroup at index " + i + " mismatch",
+ equalsPropertyGroup(expected.get(i), actual.get(i)));
+ }
+ return true;
+ }
+
+ /**
+ * Compares two PropertyGroup objects for equality.
+ *
+ * @param expected the expected PropertyGroup
+ * @param actual the actual PropertyGroup
+ * @return true if both PropertyGroup objects are equal, false otherwise
+ */
+ private static boolean equalsPropertyGroup(PropertyGroup expected,
PropertyGroup actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals(
+ "PropertyGroup prefix mismatch", expected.getPrefix(),
actual.getPrefix());
+ Assert.assertEquals(
+ "PropertyGroup file type mismatch", expected.getFileType(),
actual.getFileType());
+ Assert.assertTrue(
+ "PropertyGroup properties mismatch",
+ equalsPropertyList(expected.getPropertyList(),
actual.getPropertyList()));
+ return true;
+ }
+
+ /**
+ * Compares two lists of Property objects for equality.
+ *
+ * @param expected the expected list of Property objects
+ * @param actual the actual list of Property objects
+ * @return true if both lists are equal, false otherwise
+ */
+ private static boolean equalsPropertyList(List<Property> expected,
List<Property> actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null || expected.size() !=
actual.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < expected.size(); i++) {
+ Assert.assertTrue(
+ "Property at index " + i + " mismatch",
+ equalsProperty(expected.get(i), actual.get(i)));
+ }
+ return true;
+ }
+
+ /**
+ * Compares two Property objects for equality.
+ *
+ * @param expected the expected Property
+ * @param actual the actual Property
+ * @return true if both Property objects are equal, false otherwise
+ */
+ private static boolean equalsProperty(Property expected, Property actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals("Property name mismatch", expected.getName(),
actual.getName());
+ Assert.assertEquals(
+ "Property primary flag mismatch", expected.isPrimary(),
actual.isPrimary());
+ Assert.assertEquals(
+ "Property nullable flag mismatch", expected.isNullable(),
actual.isNullable());
+ Assert.assertEquals(
+ "Property data type mismatch", expected.getDataType(),
actual.getDataType());
+ return true;
+ }
+
+ /**
+ * Compares two maps of AdjacentList objects for equality.
+ *
+ * @param expected the expected map of AdjacentList objects
+ * @param actual the actual map of AdjacentList objects
+ * @return true if both maps are equal, false otherwise
+ */
+ private static boolean equalsAdjacentListMap(
+ Map<AdjListType, AdjacentList> expected, Map<AdjListType,
AdjacentList> actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null || expected.size() !=
actual.size()) {
+ return false;
+ }
+
+ for (Map.Entry<AdjListType, AdjacentList> entry : expected.entrySet())
{
+ AdjacentList actualValue = actual.get(entry.getKey());
+ Assert.assertTrue(
+ "AdjacentList for type " + entry.getKey() + " mismatch",
+ equalsAdjacentList(entry.getValue(), actualValue));
+ }
+ return true;
+ }
+
+ /**
+ * Compares two AdjacentList objects for equality.
+ *
+ * @param expected the expected AdjacentList
+ * @param actual the actual AdjacentList
+ * @return true if both AdjacentList objects are equal, false otherwise
+ */
+ private static boolean equalsAdjacentList(AdjacentList expected,
AdjacentList actual) {
+ if (expected == actual) {
+ return true;
+ }
+ if (expected == null || actual == null) {
+ return false;
+ }
+
+ Assert.assertEquals("AdjacentList type mismatch", expected.getType(),
actual.getType());
+ Assert.assertEquals(
+ "AdjacentList file type mismatch", expected.getFileType(),
actual.getFileType());
+ Assert.assertEquals(
+ "AdjacentList prefix mismatch", expected.getPrefix(),
actual.getPrefix());
+ return true;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]