This is an automated email from the ASF dual-hosted git repository.
opwvhk pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/branch-1.11 by this push:
new 6d7ebf365 AVRO-3486: Set namespace with protocol fullName (#1637)
6d7ebf365 is described below
commit 6d7ebf365ad4bd9806b18fcf34a9aa8f1d700838
Author: Oscar Westra van Holthe - Kind <[email protected]>
AuthorDate: Tue Aug 15 21:20:06 2023 +0200
AVRO-3486: Set namespace with protocol fullName (#1637)
* AVRO-3486: Set namespace with protocol fullName
When parsing or creating a protocol, use both the name and namespace
given to determine the actual name, namespace and fullName.
Reason: the spec says "The name and namespace qualification rules
defined for schema objects apply to protocols as well."
---
.../src/main/java/org/apache/avro/Protocol.java | 43 +++++++++++++---------
.../test/java/org/apache/avro/TestProtocol.java | 23 ++++++++++--
lang/java/compiler/src/test/idl/input/bar.avpr | 3 +-
lang/java/compiler/src/test/idl/output/import.avpr | 10 ++++-
.../compiler/src/test/idl/output/nestedimport.avpr | 11 +++++-
5 files changed, 66 insertions(+), 24 deletions(-)
diff --git a/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
b/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
index ff9968895..e01a3c73e 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
@@ -274,15 +274,29 @@ public class Protocol extends JsonProperties {
public Protocol(String name, String doc, String namespace) {
super(PROTOCOL_RESERVED);
- this.name = name;
+ setName(name, namespace);
this.doc = doc;
- this.namespace = namespace;
}
public Protocol(String name, String namespace) {
this(name, null, namespace);
}
+ private void setName(String name, String namespace) {
+ int lastDot = name.lastIndexOf('.');
+ if (lastDot < 0) {
+ this.name = name;
+ this.namespace = namespace;
+ } else {
+ this.name = name.substring(lastDot + 1);
+ this.namespace = name.substring(0, lastDot);
+ }
+ if (this.namespace != null && this.namespace.isEmpty()) {
+ this.namespace = null;
+ }
+ types.space(this.namespace);
+ }
+
/** The name of this protocol. */
public String getName() {
return name;
@@ -488,20 +502,22 @@ public class Protocol extends JsonProperties {
}
private void parse(JsonNode json) {
- parseNamespace(json);
- parseName(json);
+ parseNameAndNamespace(json);
parseTypes(json);
parseMessages(json);
parseDoc(json);
parseProps(json);
}
- private void parseNamespace(JsonNode json) {
- JsonNode nameNode = json.get("namespace");
- if (nameNode == null)
- return; // no namespace defined
- this.namespace = nameNode.textValue();
- types.space(this.namespace);
+ private void parseNameAndNamespace(JsonNode json) {
+ JsonNode nameNode = json.get("protocol");
+ if (nameNode == null) {
+ throw new SchemaParseException("No protocol name specified: " + json);
+ }
+ JsonNode namespaceNode = json.get("namespace");
+ String namespace = namespaceNode == null ? null :
namespaceNode.textValue();
+
+ setName(nameNode.textValue(), namespace);
}
private void parseDoc(JsonNode json) {
@@ -515,13 +531,6 @@ public class Protocol extends JsonProperties {
return nameNode.textValue();
}
- private void parseName(JsonNode json) {
- JsonNode nameNode = json.get("protocol");
- if (nameNode == null)
- throw new SchemaParseException("No protocol name specified: " + json);
- this.name = nameNode.textValue();
- }
-
private void parseTypes(JsonNode json) {
JsonNode defs = json.get("types");
if (defs == null)
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java
b/lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java
index 881b929ea..5af522235 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java
@@ -17,9 +17,6 @@
*/
package org.apache.avro;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.junit.Assert.*;
@@ -27,13 +24,31 @@ import org.junit.Test;
public class TestProtocol {
+ @Test
+ public void testNamespaceAndNameRules() {
+ Protocol p1 = new Protocol("P", null, "foo");
+ Protocol p2 = new Protocol("foo.P", null, null);
+ Protocol p3 = new Protocol("foo.P", null, "bar");
+ assertEquals(p1.getName(), p2.getName());
+ assertEquals(p1.getNamespace(), p2.getNamespace());
+ assertEquals(p1.getName(), p3.getName());
+ assertEquals(p1.getNamespace(), p3.getNamespace());
+
+ // The following situation is allowed, even if confusing, because the
+ // specification describes this algorithm without specifying that the
resulting
+ // namespace mst be non-empty.
+ Protocol invalidName = new Protocol(".P", null, "ignored");
+ assertNull(invalidName.getNamespace());
+ assertEquals("P", invalidName.getName());
+ }
+
@Test
public void testPropEquals() {
Protocol p1 = new Protocol("P", null, "foo");
p1.addProp("a", "1");
Protocol p2 = new Protocol("P", null, "foo");
p2.addProp("a", "2");
- assertFalse(p1.equals(p2));
+ assertNotEquals(p1, p2);
}
@Test
diff --git a/lang/java/compiler/src/test/idl/input/bar.avpr
b/lang/java/compiler/src/test/idl/input/bar.avpr
index 5e9b194a0..ea8b0d4be 100644
--- a/lang/java/compiler/src/test/idl/input/bar.avpr
+++ b/lang/java/compiler/src/test/idl/input/bar.avpr
@@ -1,2 +1,3 @@
{"protocol": "org.foo.Bar",
- "messages": { "bar": {"request": [], "response": "null"}}}
+ "types": [{"name": "AorB", "type": "enum", "symbols": ["A", "B"], "default":
"A"}],
+ "messages": { "bar": {"request": [{"name": "choice", "type":
"AorB"}],"response": "null"}}}
diff --git a/lang/java/compiler/src/test/idl/output/import.avpr
b/lang/java/compiler/src/test/idl/output/import.avpr
index e6701ad94..b0093492d 100644
--- a/lang/java/compiler/src/test/idl/output/import.avpr
+++ b/lang/java/compiler/src/test/idl/output/import.avpr
@@ -3,6 +3,11 @@
"namespace" : "org.foo",
"doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more
contributor license agreements. See the NOTICE file\ndistributed with this
work for additional information\nregarding copyright ownership. The ASF
licenses this file\nto you under the Apache License, Version 2.0
(the\n\"License\"); you may not use this file except in compliance\nwith the
License. You may obtain a copy of the License at\n\n
https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by [...]
"types" : [ {
+ "type" : "enum",
+ "name" : "AorB",
+ "symbols" : ["A", "B"],
+ "default" : "A"
+ }, {
"type" : "enum",
"name" : "Position",
"namespace" : "avro.examples.baseball",
@@ -111,7 +116,10 @@
"response" : "null"
},
"bar" : {
- "request" : [ ],
+ "request" : [ {
+ "name" : "choice",
+ "type" : "AorB"
+ } ],
"response" : "null"
},
"bazm" : {
diff --git a/lang/java/compiler/src/test/idl/output/nestedimport.avpr
b/lang/java/compiler/src/test/idl/output/nestedimport.avpr
index 802736271..f1060b0d7 100644
--- a/lang/java/compiler/src/test/idl/output/nestedimport.avpr
+++ b/lang/java/compiler/src/test/idl/output/nestedimport.avpr
@@ -4,6 +4,12 @@
"doc" : "Licensed to the Apache Software Foundation (ASF) under one\nor more
contributor license agreements. See the NOTICE file\ndistributed with this
work for additional information\nregarding copyright ownership. The ASF
licenses this file\nto you under the Apache License, Version 2.0
(the\n\"License\"); you may not use this file except in compliance\nwith the
License. You may obtain a copy of the License at\n\n
https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by [...]
"version" : "1.0.5",
"types" : [ {
+ "type" : "enum",
+ "name" : "AorB",
+ "namespace" : "org.foo",
+ "symbols" : ["A", "B"],
+ "default" : "A"
+ }, {
"type" : "enum",
"name" : "Position",
"namespace" : "avro.examples.baseball",
@@ -66,7 +72,10 @@
"response" : "null"
},
"bar" : {
- "request" : [ ],
+ "request" : [ {
+ "name" : "choice",
+ "type" : "org.foo.AorB"
+ } ],
"response" : "null"
}
}