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 24dbe1bb feat(java,info): support multi-property in yaml (#780)
24dbe1bb is described below
commit 24dbe1bb0c89888e5482b9aafeb25b890fbea21c
Author: Xiaokang Yang <[email protected]>
AuthorDate: Mon Dec 8 20:20:00 2025 +0800
feat(java,info): support multi-property in yaml (#780)
* add multi property
* remove cardinality in edgeInfo
* fix copilot comment
* format code
* try to fix
* update
---
.../java/org/apache/graphar/info/EdgeInfo.java | 11 +
.../java/org/apache/graphar/info/GraphInfo.java | 9 +
.../java/org/apache/graphar/info/Property.java | 23 +-
.../org/apache/graphar/info/PropertyGroup.java | 9 +
.../java/org/apache/graphar/info/VertexInfo.java | 11 +
.../graphar/info/saver/BaseGraphInfoSaver.java | 13 +
.../org/apache/graphar/info/type/Cardinality.java | 60 ++++
.../org/apache/graphar/info/yaml/PropertyYaml.java | 25 +-
.../org/apache/graphar/info/yaml/VertexYaml.java | 13 +
.../org/apache/graphar/info/GraphInfoTest.java | 7 +
.../org/apache/graphar/info/MultiPropertyTest.java | 353 +++++++++++++++++++++
.../org/apache/graphar/info/TestDataFactory.java | 11 +
.../java/org/apache/graphar/info/TestUtil.java | 9 +
.../apache/graphar/info/TestVerificationUtils.java | 4 +
14 files changed, 551 insertions(+), 7 deletions(-)
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 cd18c16d..91cb48c4 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
@@ -32,6 +32,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.graphar.info.type.AdjListType;
+import org.apache.graphar.info.type.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.yaml.EdgeYaml;
import org.apache.graphar.info.yaml.GraphYaml;
@@ -496,12 +497,18 @@ public class EdgeInfo {
}
public void dump(Writer output) {
+ if (!isValidated()) {
+ throw new IllegalStateException("EdgeInfo is not valid and cannot
be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
EdgeYaml edgeYaml = new EdgeYaml(this);
yaml.dump(edgeYaml, output);
}
public String dump() {
+ if (!isValidated()) {
+ throw new IllegalStateException("EdgeInfo is not valid and cannot
be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
EdgeYaml edgeYaml = new EdgeYaml(this);
return yaml.dump(edgeYaml);
@@ -626,6 +633,10 @@ public class EdgeInfo {
}
for (Property p : pg.getPropertyList()) {
+ if (p.getCardinality() != Cardinality.SINGLE) {
+ // edge property only supports single cardinality
+ return false;
+ }
if (propertyNameSet.contains(p.getName())) {
return false;
}
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 e0ed2bfa..2e5661ee 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
@@ -128,18 +128,27 @@ public class GraphInfo {
}
public void dump(URI storeUri, Writer output) {
+ if (!isValidated()) {
+ throw new IllegalStateException("GraphInfo is not valid and cannot
be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
GraphYaml graphYaml = new GraphYaml(storeUri, this);
yaml.dump(graphYaml, output);
}
public String dump(URI storeUri) {
+ if (!isValidated()) {
+ throw new IllegalStateException("GraphInfo is not valid and cannot
be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
GraphYaml graphYaml = new GraphYaml(storeUri, this);
return yaml.dump(graphYaml);
}
public String dump() {
+ if (!isValidated()) {
+ throw new IllegalStateException("GraphInfo is not valid and cannot
be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
GraphYaml graphYaml = new GraphYaml(this);
return yaml.dump(graphYaml);
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
index 1221ebc1..2d63d29f 100644
--- a/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
+++ b/maven-projects/info/src/main/java/org/apache/graphar/info/Property.java
@@ -19,27 +19,44 @@
package org.apache.graphar.info;
+import org.apache.graphar.info.type.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.yaml.PropertyYaml;
public class Property {
private final String name;
private final DataType dataType;
+ private final Cardinality cardinality;
private final boolean primary;
private final boolean nullable;
public Property(String name, DataType dataType, boolean primary, boolean
nullable) {
+ this(name, dataType, Cardinality.SINGLE, primary, nullable);
+ }
+
+ public Property(
+ String name,
+ DataType dataType,
+ Cardinality cardinality,
+ boolean primary,
+ boolean nullable) {
this.name = name;
this.dataType = dataType;
+ this.cardinality = cardinality;
this.primary = primary;
this.nullable = nullable;
}
- Property(PropertyYaml yamlParser) {
+ public Property(PropertyYaml yamlParser) {
this.name = yamlParser.getName();
this.dataType = DataType.fromString(yamlParser.getData_type());
this.primary = yamlParser.getIs_primary();
this.nullable = yamlParser.getIs_nullable();
+ Cardinality cardinality = Cardinality.SINGLE;
+ if (yamlParser.getCardinality() != null &&
!yamlParser.getCardinality().isEmpty()) {
+ cardinality = Cardinality.fromString(yamlParser.getCardinality());
+ }
+ this.cardinality = cardinality;
}
public String getName() {
@@ -57,4 +74,8 @@ public class Property {
public boolean isNullable() {
return nullable;
}
+
+ public Cardinality getCardinality() {
+ return cardinality;
+ }
}
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 ae1fdc4e..2aceacea 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
@@ -28,6 +28,7 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.graphar.info.type.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.type.FileType;
import org.apache.graphar.util.GeneralParams;
@@ -137,6 +138,9 @@ public class PropertyGroup implements Iterable<Property> {
if (property.getDataType() == DataType.LIST && fileType ==
FileType.CSV) {
return false;
}
+ if (property.getCardinality() != Cardinality.SINGLE && fileType ==
FileType.CSV) {
+ return false;
+ }
}
return true;
@@ -216,6 +220,11 @@ class PropertyGroups {
return propertyGroupList.size();
}
+ public Cardinality getCardinality(String propertyName) {
+ checkPropertyExist(propertyName);
+ return properties.get(propertyName).getCardinality();
+ }
+
DataType getPropertyType(String propertyName) {
checkPropertyExist(propertyName);
return properties.get(propertyName).getDataType();
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 3a56ffb3..5821216f 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
@@ -26,6 +26,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import org.apache.graphar.info.type.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.yaml.GraphYaml;
import org.apache.graphar.info.yaml.VertexYaml;
@@ -186,6 +187,10 @@ public class VertexInfo {
return propertyGroups.getPropertyGroupNum();
}
+ public Cardinality getCardinality(String propertyName) {
+ return propertyGroups.getCardinality(propertyName);
+ }
+
public DataType getPropertyType(String propertyName) {
return propertyGroups.getPropertyType(propertyName);
}
@@ -225,12 +230,18 @@ public class VertexInfo {
}
public void dump(Writer output) {
+ if (!isValidated()) {
+ throw new IllegalStateException("VertexInfo is not valid and
cannot be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
VertexYaml vertexYaml = new VertexYaml(this);
yaml.dump(vertexYaml, output);
}
public String dump() {
+ if (!isValidated()) {
+ throw new IllegalStateException("VertexInfo is not valid and
cannot be dumped.");
+ }
Yaml yaml = new Yaml(GraphYaml.getRepresenter(),
GraphYaml.getDumperOptions());
VertexYaml vertexYaml = new VertexYaml(this);
return yaml.dump(vertexYaml);
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
index a59bdcc7..680b877b 100644
---
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
@@ -32,6 +32,10 @@ public abstract class BaseGraphInfoSaver implements
GraphInfoSaver {
@Override
public void save(URI graphInfoUri, GraphInfo graphInfo) throws IOException
{
+ // if graphInfoUri is a directory then save to
${graphInfo.name}.graph.yml
+ if (graphInfoUri.getPath().endsWith("/")) {
+ graphInfoUri = URI.create(graphInfoUri.toString() +
graphInfo.getName() + ".graph.yml");
+ }
Writer writer = writeYaml(graphInfoUri);
graphInfo.dump(graphInfoUri, writer);
writer.close();
@@ -48,6 +52,11 @@ public abstract class BaseGraphInfoSaver implements
GraphInfoSaver {
@Override
public void save(URI vertexInfoUri, VertexInfo vertexInfo) throws
IOException {
+ // if vertexInfoUri is a directory then save to
${vertexInfo.type}.vertex.yml
+ if (vertexInfoUri.getPath().endsWith("/")) {
+ vertexInfoUri =
+ URI.create(vertexInfoUri.toString() + vertexInfo.getType()
+ ".vertex.yml");
+ }
Writer vertexWriter = writeYaml(vertexInfoUri);
vertexInfo.dump(vertexWriter);
vertexWriter.close();
@@ -55,6 +64,10 @@ public abstract class BaseGraphInfoSaver implements
GraphInfoSaver {
@Override
public void save(URI edgeInfoUri, EdgeInfo edgeInfo) throws IOException {
+ // if edgeInfoUri is a directory then save to
${edgeInfo.getConcat()}.edge.yml
+ if (edgeInfoUri.getPath().endsWith("/")) {
+ edgeInfoUri = URI.create(edgeInfoUri.toString() +
edgeInfo.getConcat() + ".edge.yml");
+ }
Writer edgeWriter = writeYaml(edgeInfoUri);
edgeInfo.dump(edgeWriter);
edgeWriter.close();
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/type/Cardinality.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/Cardinality.java
new file mode 100644
index 00000000..b50a170a
--- /dev/null
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/type/Cardinality.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.graphar.info.type;
+
+/** Defines how multiple values are handled for a given property key. */
+public enum Cardinality {
+ /** Single value property */
+ SINGLE,
+ /** List of values property */
+ LIST,
+ /** Set of values property (no duplicates) */
+ SET;
+
+ @Override
+ public String toString() {
+ switch (this) {
+ case SINGLE:
+ return "single";
+ case LIST:
+ return "list";
+ case SET:
+ return "set";
+ default:
+ throw new IllegalArgumentException("Unknown cardinality: " +
this);
+ }
+ }
+
+ public static Cardinality fromString(String cardinality) {
+ if (cardinality == null) {
+ return null;
+ }
+ switch (cardinality) {
+ case "single":
+ return SINGLE;
+ case "list":
+ return LIST;
+ case "set":
+ return SET;
+ default:
+ throw new IllegalArgumentException("Unknown cardinality: " +
cardinality);
+ }
+ }
+}
diff --git
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
index ee98a339..aedd666f 100644
---
a/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
+++
b/maven-projects/info/src/main/java/org/apache/graphar/info/yaml/PropertyYaml.java
@@ -21,19 +21,21 @@ package org.apache.graphar.info.yaml;
import java.util.Optional;
import org.apache.graphar.info.Property;
-import org.apache.graphar.info.type.DataType;
+import org.apache.graphar.info.type.Cardinality;
public class PropertyYaml {
private String name;
private String data_type;
private boolean is_primary;
private Optional<Boolean> is_nullable;
+ private String cardinality;
public PropertyYaml() {
this.name = "";
this.data_type = "";
this.is_primary = false;
this.is_nullable = Optional.empty();
+ this.cardinality = null;
}
public PropertyYaml(Property property) {
@@ -41,14 +43,14 @@ public class PropertyYaml {
this.data_type = property.getDataType().toString();
this.is_primary = property.isPrimary();
this.is_nullable = Optional.of(property.isNullable());
+ this.cardinality =
+ property.getCardinality() == Cardinality.SINGLE
+ ? null
+ : property.getCardinality().toString();
}
Property toProperty() {
- return new Property(
- name,
- DataType.fromString(data_type),
- is_primary,
- is_nullable.orElseGet(() -> !is_primary));
+ return new Property(this);
}
public String getName() {
@@ -82,4 +84,15 @@ public class PropertyYaml {
public void setIs_nullable(boolean is_nullable) {
this.is_nullable = Optional.of(is_nullable);
}
+
+ public String getCardinality() {
+ if (cardinality == null) {
+ return null;
+ }
+ return Cardinality.SINGLE.toString().equals(cardinality) ? null :
cardinality;
+ }
+
+ public void setCardinality(String cardinality) {
+ this.cardinality = cardinality;
+ }
}
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 345e0369..42d5a3fc 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
@@ -30,6 +30,7 @@ public class VertexYaml {
private String type;
private long chunk_size;
private List<PropertyGroupYaml> property_groups;
+ private List<String> labels;
private String prefix;
private String version;
@@ -37,6 +38,7 @@ public class VertexYaml {
this.type = "";
this.chunk_size = 0;
this.property_groups = new ArrayList<>();
+ this.labels = null;
this.prefix = "";
this.version = "";
}
@@ -80,6 +82,17 @@ public class VertexYaml {
this.property_groups = property_groups;
}
+ public List<String> getLabels() {
+ if (labels == null) {
+ return null;
+ }
+ return labels.isEmpty() ? null : labels;
+ }
+
+ public void setLabels(List<String> labels) {
+ this.labels = labels;
+ }
+
public String getPrefix() {
return prefix;
}
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 b4ade718..77efdc6b 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
@@ -27,6 +27,7 @@ import java.util.List;
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.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.type.FileType;
import org.junit.AfterClass;
@@ -169,6 +170,8 @@ public class GraphInfoTest {
Assert.assertEquals("id", idProperty.getName());
Assert.assertEquals(DataType.INT64, idProperty.getDataType());
Assert.assertEquals(DataType.INT64,
personVertexInfo.getPropertyType("id"));
+ Assert.assertEquals(Cardinality.SINGLE, idProperty.getCardinality());
+ Assert.assertEquals(Cardinality.SINGLE,
personVertexInfo.getCardinality("id"));
Assert.assertTrue(idProperty.isPrimary());
Assert.assertTrue(personVertexInfo.isPrimaryKey("id"));
Assert.assertFalse(idProperty.isNullable());
@@ -196,18 +199,21 @@ public class GraphInfoTest {
Assert.assertTrue(personVertexInfo.hasProperty("firstName"));
Assert.assertEquals("firstName", firstNameProperty.getName());
Assert.assertEquals(DataType.STRING, firstNameProperty.getDataType());
+ Assert.assertEquals(Cardinality.SINGLE,
firstNameProperty.getCardinality());
Assert.assertFalse(firstNameProperty.isPrimary());
Assert.assertTrue(firstNameProperty.isNullable());
Property lastNameProperty =
firstName_lastName_gender.getPropertyList().get(1);
Assert.assertTrue(personVertexInfo.hasProperty("lastName"));
Assert.assertEquals("lastName", lastNameProperty.getName());
Assert.assertEquals(DataType.STRING, lastNameProperty.getDataType());
+ Assert.assertEquals(Cardinality.SINGLE,
lastNameProperty.getCardinality());
Assert.assertFalse(lastNameProperty.isPrimary());
Assert.assertTrue(lastNameProperty.isNullable());
Property genderProperty =
firstName_lastName_gender.getPropertyList().get(2);
Assert.assertTrue(personVertexInfo.hasProperty("gender"));
Assert.assertEquals("gender", genderProperty.getName());
Assert.assertEquals(DataType.STRING, genderProperty.getDataType());
+ Assert.assertEquals(Cardinality.SINGLE,
genderProperty.getCardinality());
Assert.assertFalse(genderProperty.isPrimary());
Assert.assertTrue(genderProperty.isNullable());
}
@@ -351,6 +357,7 @@ public class GraphInfoTest {
Assert.assertEquals("creationDate", property.getName());
Assert.assertEquals(DataType.STRING, property.getDataType());
Assert.assertEquals(DataType.STRING,
knowsEdgeInfo.getPropertyType("creationDate"));
+ Assert.assertEquals(Cardinality.SINGLE, property.getCardinality());
Assert.assertFalse(property.isPrimary());
Assert.assertFalse(knowsEdgeInfo.isPrimaryKey("creationDate"));
Assert.assertTrue(property.isNullable());
diff --git
a/maven-projects/info/src/test/java/org/apache/graphar/info/MultiPropertyTest.java
b/maven-projects/info/src/test/java/org/apache/graphar/info/MultiPropertyTest.java
new file mode 100644
index 00000000..59a40e37
--- /dev/null
+++
b/maven-projects/info/src/test/java/org/apache/graphar/info/MultiPropertyTest.java
@@ -0,0 +1,353 @@
+/*
+ * 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 java.util.Arrays;
+import java.util.List;
+import org.apache.graphar.info.loader.GraphInfoLoader;
+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.type.AdjListType;
+import org.apache.graphar.info.type.Cardinality;
+import org.apache.graphar.info.type.DataType;
+import org.apache.graphar.info.type.FileType;
+import org.apache.graphar.info.yaml.PropertyYaml;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MultiPropertyTest extends BaseFileSystemTest {
+
+ private String testSaveDirectory;
+ private GraphInfoLoader graphInfoLoader;
+ private GraphInfoSaver graphInfoSaver;
+ private Property singleProperty;
+ private Property listProperty;
+ private Property setProperty;
+
+ @Before
+ public void setUp() {
+ testSaveDirectory =
createCleanTestDirectory("ldbc_multi_property_sample/");
+ graphInfoLoader = new LocalFileSystemStringGraphInfoLoader();
+ graphInfoSaver = new LocalFileSystemYamlGraphSaver();
+ singleProperty =
+ TestDataFactory.createProperty("single_email",
DataType.STRING, false, true);
+ listProperty =
+ TestDataFactory.createProperty(
+ "list_email", DataType.STRING, Cardinality.LIST,
false, true);
+ setProperty =
+ TestDataFactory.createProperty(
+ "set_email", DataType.STRING, Cardinality.SET, false,
true);
+ }
+
+ @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 testPropertyWithCardinality() {
+ // Test single cardinality property
+ Assert.assertEquals("single_email", singleProperty.getName());
+ Assert.assertEquals(DataType.STRING, singleProperty.getDataType());
+ Assert.assertFalse(singleProperty.isPrimary());
+ Assert.assertTrue(singleProperty.isNullable());
+ Assert.assertEquals(Cardinality.SINGLE,
singleProperty.getCardinality());
+
+ // Test list cardinality property
+ Assert.assertEquals("list_email", listProperty.getName());
+ Assert.assertEquals(DataType.STRING, listProperty.getDataType());
+ Assert.assertFalse(listProperty.isPrimary());
+ Assert.assertTrue(listProperty.isNullable());
+ Assert.assertEquals(Cardinality.LIST, listProperty.getCardinality());
+
+ // Test set cardinality property
+ Assert.assertEquals("set_email", setProperty.getName());
+ Assert.assertEquals(DataType.STRING, setProperty.getDataType());
+ Assert.assertFalse(setProperty.isPrimary());
+ Assert.assertTrue(setProperty.isNullable());
+ Assert.assertEquals(Cardinality.SET, setProperty.getCardinality());
+ }
+
+ @Test
+ public void testPropertyGroupWithMultiProperties() {
+ // Create property group with different cardinality properties
+ PropertyGroup propertyGroup =
+ TestDataFactory.createPropertyGroup(
+ Arrays.asList(singleProperty, listProperty,
setProperty),
+ FileType.PARQUET,
+ "emails/");
+
+ Assert.assertEquals(3, propertyGroup.size());
+ Assert.assertEquals(FileType.PARQUET, propertyGroup.getFileType());
+ Assert.assertEquals("emails/", propertyGroup.getPrefix());
+
+ // Test iteration over properties
+ int count = 0;
+ for (Property property : propertyGroup) {
+ count++;
+ if ("single_email".equals(property.getName())) {
+ Assert.assertEquals(Cardinality.SINGLE,
property.getCardinality());
+ } else if ("list_email".equals(property.getName())) {
+ Assert.assertEquals(Cardinality.LIST,
property.getCardinality());
+ } else if ("set_email".equals(property.getName())) {
+ Assert.assertEquals(Cardinality.SET,
property.getCardinality());
+ }
+ }
+ Assert.assertEquals(3, count);
+ }
+
+ @Test
+ public void testPropertyYamlWithCardinality() {
+ // Test converting Property to PropertyYaml and back
+ PropertyYaml singleYaml = new PropertyYaml(singleProperty);
+ PropertyYaml listYaml = new PropertyYaml(listProperty);
+ PropertyYaml setYaml = new PropertyYaml(setProperty);
+
+ // Check YAML representations
+ Assert.assertEquals("single_email", singleYaml.getName());
+ Assert.assertNull(singleYaml.getCardinality());
+
+ Assert.assertEquals("list_email", listYaml.getName());
+ Assert.assertEquals("list", listYaml.getCardinality());
+
+ Assert.assertEquals("set_email", setYaml.getName());
+ Assert.assertEquals("set", setYaml.getCardinality());
+
+ // Convert back to Property objects
+ Property singlePropFromYaml = new Property(singleYaml);
+ Property listPropFromYaml = new Property(listYaml);
+ Property setPropFromYaml = new Property(setYaml);
+
+ // Verify properties are correctly restored
+ Assert.assertEquals(singleProperty.getName(),
singlePropFromYaml.getName());
+ Assert.assertEquals(singleProperty.getDataType(),
singlePropFromYaml.getDataType());
+ Assert.assertEquals(singleProperty.getCardinality(),
singlePropFromYaml.getCardinality());
+
+ Assert.assertEquals(listProperty.getName(),
listPropFromYaml.getName());
+ Assert.assertEquals(listProperty.getDataType(),
listPropFromYaml.getDataType());
+ Assert.assertEquals(listProperty.getCardinality(),
listPropFromYaml.getCardinality());
+
+ Assert.assertEquals(setProperty.getName(), setPropFromYaml.getName());
+ Assert.assertEquals(setProperty.getDataType(),
setPropFromYaml.getDataType());
+ Assert.assertEquals(setProperty.getCardinality(),
setPropFromYaml.getCardinality());
+ }
+
+ @Test
+ public void testDefaultCardinality() {
+ // Test that properties created without specifying cardinality default
to SINGLE
+ Property defaultProperty =
+ TestDataFactory.createProperty("default_prop",
DataType.STRING, false, true);
+ Assert.assertEquals(Cardinality.SINGLE,
defaultProperty.getCardinality());
+
+ // Test YAML conversion with default cardinality
+ PropertyYaml defaultYaml = new PropertyYaml(defaultProperty);
+ Assert.assertNull(defaultYaml.getCardinality());
+
+ Property defaultPropFromYaml = new Property(defaultYaml);
+ Assert.assertEquals(Cardinality.SINGLE,
defaultPropFromYaml.getCardinality());
+ }
+
+ @Test
+ public void testInvalidCardinalityHandling() {
+ // Test handling of invalid cardinality in YAML
+ PropertyYaml invalidYaml = new PropertyYaml();
+ invalidYaml.setName("invalid_prop");
+ invalidYaml.setData_type("string");
+ invalidYaml.setCardinality("INVALID"); // This should throw an
IllegalArgumentException
+ IllegalArgumentException illegalArgumentException =
+ Assert.assertThrows(
+ IllegalArgumentException.class, () -> new
Property(invalidYaml));
+ Assert.assertEquals("Unknown cardinality: INVALID",
illegalArgumentException.getMessage());
+ }
+
+ @Test
+ public void testEdgeInfoWithMultiProperty() throws IOException {
+ Property weights =
+ TestDataFactory.createProperty(
+ "weights", DataType.DOUBLE, Cardinality.LIST, false,
true);
+ PropertyGroup weightsPg =
+ TestDataFactory.createPropertyGroup(
+ Arrays.asList(weights), FileType.CSV, "weights/");
+ AdjacentList orderedBySource =
+ TestDataFactory.createAdjacentList(
+ AdjListType.ordered_by_source, FileType.PARQUET,
"ordered_by_source/");
+ EdgeInfo knowsEdgeInfo =
+ EdgeInfo.builder()
+ .srcType("person")
+ .edgeType("knows")
+ .dstType("person")
+ .chunkSize(1024)
+ .srcChunkSize(100)
+ .dstChunkSize(100)
+ .directed(false)
+ .prefix("edge/person_knows_person/")
+ .version("gar/v1")
+ .addAdjacentList(orderedBySource)
+ .addPropertyGroups(List.of(weightsPg))
+ .build();
+ Assert.assertFalse(knowsEdgeInfo.isValidated());
+ }
+
+ @Test
+ public void testListPropertyInCsv() {
+ Property emails =
+ TestDataFactory.createProperty(
+ "emails", DataType.STRING, Cardinality.LIST, false,
true);
+ PropertyGroup emailInCsv =
+ TestDataFactory.createPropertyGroup(List.of(emails),
FileType.CSV, "emails_csv/");
+ VertexInfo personVertexInfo =
+ new VertexInfo("person", 1000, List.of(emailInCsv),
"vertex/person/", "gar/v1");
+ Assert.assertFalse(personVertexInfo.isValidated());
+ }
+
+ @Test
+ public void testSetPropertyInCsv() {
+ Property emails =
+ TestDataFactory.createProperty(
+ "emails", DataType.STRING, Cardinality.SET, false,
true);
+ PropertyGroup emailInCsv =
+ TestDataFactory.createPropertyGroup(List.of(emails),
FileType.CSV, "emails_csv/");
+ VertexInfo personVertexInfo =
+ new VertexInfo("person", 1000, List.of(emailInCsv),
"vertex/person/", "gar/v1");
+ Assert.assertFalse(personVertexInfo.isValidated());
+ }
+
+ @Test
+ public void testGraphInfoWithMultiPropertyYamlLoadAndSave() throws
IOException {
+ // Create a GraphInfo with multi-property support
+ Property id = TestDataFactory.createProperty("id", DataType.INT64,
true, false);
+ Property name = TestDataFactory.createProperty("name",
DataType.STRING, false, true);
+ Property emails =
+ TestDataFactory.createProperty(
+ "emails", DataType.STRING, Cardinality.LIST, false,
true);
+ Property tags =
+ TestDataFactory.createProperty(
+ "tags", DataType.STRING, Cardinality.SET, false, true);
+ Property creationDate =
+ TestDataFactory.createProperty("creationDate",
DataType.STRING, false, false);
+ PropertyGroup personIdGroup =
+ TestDataFactory.createPropertyGroup(List.of(id),
FileType.PARQUET, "id/");
+ PropertyGroup personInfoGroup =
+ TestDataFactory.createPropertyGroup(
+ Arrays.asList(name, emails, tags), FileType.PARQUET,
"info/");
+
+ PropertyGroup edgePropertyGroup =
+ TestDataFactory.createPropertyGroup(
+ List.of(creationDate), FileType.PARQUET,
"properties/");
+
+ // Create adjacent lists
+ AdjacentList orderedBySource =
+ TestDataFactory.createAdjacentList(
+ AdjListType.ordered_by_source, FileType.PARQUET,
"ordered_by_source/");
+ AdjacentList unorderedByDest =
+ TestDataFactory.createAdjacentList(
+ AdjListType.unordered_by_dest, FileType.PARQUET,
"unordered_by_dest/");
+
+ VertexInfo personVertexInfo =
+ new VertexInfo(
+ "person",
+ 1000,
+ Arrays.asList(personIdGroup, personInfoGroup),
+ "vertex/person/",
+ "gar/v1");
+
+ EdgeInfo knowsEdgeInfo =
+ EdgeInfo.builder()
+ .srcType("person")
+ .edgeType("knows")
+ .dstType("person")
+ .chunkSize(1024)
+ .srcChunkSize(100)
+ .dstChunkSize(100)
+ .directed(false)
+ .prefix("edge/person_knows_person/")
+ .version("gar/v1")
+ .addAdjacentList(orderedBySource)
+ .addAdjacentList(unorderedByDest)
+ .addPropertyGroups(Arrays.asList(edgePropertyGroup))
+ .build();
+
+ GraphInfo graphInfo =
+ new GraphInfo(
+ "test_graph",
+ Arrays.asList(personVertexInfo),
+ Arrays.asList(knowsEdgeInfo),
+ "/tmp/",
+ "gar/v1");
+
+ // Check that the generated YAML files contain cardinality information
+ String graphYamlFilePath = testSaveDirectory + "/test_graph.graph.yml";
+
+ // Save GraphInfo to YAML files
+ graphInfoSaver.save(URI.create(testSaveDirectory), graphInfo);
+
+ // Load GraphInfo from YAML files
+ GraphInfo loadedGraphInfo =
graphInfoLoader.loadGraphInfo(URI.create(graphYamlFilePath));
+ Assert.assertTrue(TestVerificationUtils.equalsGraphInfo(graphInfo,
loadedGraphInfo));
+ }
+
+ @Test
+ public void testLoadFromTestData() throws IOException {
+ URI GRAPH_PATH_URI = TestUtil.getLdbcGraphURI();
+ GraphInfo graphInfo = graphInfoLoader.loadGraphInfo(GRAPH_PATH_URI);
+ VertexInfo personInfo = graphInfo.getVertexInfo("person");
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("firstName"));
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("lastName"));
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("gender"));
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("locationIP"));
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("browserUsed"));
+ Assert.assertEquals(Cardinality.SINGLE,
personInfo.getCardinality("id"));
+ Assert.assertEquals(Cardinality.LIST,
personInfo.getCardinality("emails"));
+ }
+
+ @Test
+ public void testDumpCardinalities() throws IOException {
+ Property id = new Property("id", DataType.INT64, true, false);
+ PropertyGroup properties = new PropertyGroup(List.of(id),
FileType.PARQUET, "id/");
+ VertexInfo vertexInfo =
+ new VertexInfo("person", 100, List.of(properties),
"vertex/person/", "gar/v1");
+ String dump = vertexInfo.dump();
+ Assert.assertFalse(dump.contains("cardinality:"));
+
+ id = new Property("id", DataType.INT64, Cardinality.SINGLE, true,
false);
+ properties = new PropertyGroup(List.of(id), FileType.PARQUET, "id/");
+ vertexInfo = new VertexInfo("person", 100, List.of(properties),
"vertex/person/", "gar/v1");
+ dump = vertexInfo.dump();
+ Assert.assertFalse(dump.contains("cardinality:"));
+
+ id = new Property("id", DataType.INT64, Cardinality.LIST, true, false);
+ properties = new PropertyGroup(List.of(id), FileType.PARQUET, "id/");
+ vertexInfo = new VertexInfo("person", 100, List.of(properties),
"vertex/person/", "gar/v1");
+ dump = vertexInfo.dump();
+ Assert.assertTrue(dump.contains("cardinality: list"));
+
+ id = new Property("id", DataType.INT64, Cardinality.SET, true, false);
+ properties = new PropertyGroup(List.of(id), FileType.PARQUET, "id/");
+ vertexInfo = new VertexInfo("person", 100, List.of(properties),
"vertex/person/", "gar/v1");
+ dump = vertexInfo.dump();
+ Assert.assertTrue(dump.contains("cardinality: set"));
+ }
+}
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 b2943488..66b14e13 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
@@ -21,6 +21,7 @@ package org.apache.graphar.info;
import java.util.List;
import org.apache.graphar.info.type.AdjListType;
+import org.apache.graphar.info.type.Cardinality;
import org.apache.graphar.info.type.DataType;
import org.apache.graphar.info.type.FileType;
@@ -100,6 +101,16 @@ public class TestDataFactory {
return new Property(name, dataType, isPrimary, isNullable);
}
+ /** Creates a property with given parameters including cardinality. */
+ public static Property createProperty(
+ String name,
+ DataType dataType,
+ Cardinality cardinality,
+ boolean isPrimary,
+ boolean isNullable) {
+ return new Property(name, dataType, cardinality, isPrimary,
isNullable);
+ }
+
/** Creates a property group with given parameters. */
public static PropertyGroup createPropertyGroup(
List<Property> properties, FileType fileType, String prefix) {
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 880c6005..0b703343 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
@@ -38,6 +38,7 @@ public class TestUtil {
System.getProperty("test.output.dir", "target/test-output") + "/";
private static final String LDBC_SAMPLE_GRAPH_PATH =
"/ldbc_sample/csv/ldbc_sample.graph.yml";
+ private static final String LDBC_GRAPH_PATH =
"/ldbc/parquet/ldbc.graph.yml";
public static String getTestData() {
return GAR_TEST_DATA;
@@ -56,6 +57,14 @@ public class TestUtil {
return URI.create(getLdbcSampleGraphPath());
}
+ public static String getLdbcGraphPath() {
+ return getTestData() + "/" + LDBC_GRAPH_PATH;
+ }
+
+ public static URI getLdbcGraphURI() {
+ return URI.create(getLdbcGraphPath());
+ }
+
public static VertexInfo buildVertexInfoFromYaml(VertexYaml vertexYaml) {
return new VertexInfo(
vertexYaml.getType(),
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 fe09e6e6..ddf66067 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
@@ -389,6 +389,10 @@ public class TestVerificationUtils {
"Property nullable flag mismatch", expected.isNullable(),
actual.isNullable());
Assert.assertEquals(
"Property data type mismatch", expected.getDataType(),
actual.getDataType());
+ Assert.assertEquals(
+ "Property cardinality mismatch",
+ expected.getCardinality(),
+ actual.getCardinality());
return true;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]