Skip to content

Commit

Permalink
AVRO-3486: Set namespace with protocol fullName (#1637)
Browse files Browse the repository at this point in the history
* 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."
  • Loading branch information
opwvhk committed Aug 15, 2023
1 parent 52d9339 commit b1517d3
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 25 deletions.
43 changes: 26 additions & 17 deletions lang/java/avro/src/main/java/org/apache/avro/Protocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,29 @@ public Protocol(Protocol p) {

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;
Expand Down Expand Up @@ -488,20 +502,22 @@ private static Protocol parse(JsonParser parser) {
}

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) {
Expand All @@ -515,13 +531,6 @@ private String parseDocNode(JsonNode json) {
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)
Expand Down
25 changes: 20 additions & 5 deletions lang/java/avro/src/test/java/org/apache/avro/TestProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,31 @@
*/
package org.apache.avro;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import org.junit.jupiter.api.Test;

import static java.util.Collections.singletonMap;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

public class TestProtocol {

@Test
void namespaceAndNameRules() {
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
void propEquals() {
Protocol p1 = new Protocol("P", null, "foo");
Expand Down
3 changes: 2 additions & 1 deletion lang/java/compiler/src/test/idl/input/bar.avpr
Original file line number Diff line number Diff line change
@@ -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"}}}
10 changes: 9 additions & 1 deletion lang/java/compiler/src/test/idl/output/import.avpr
Original file line number Diff line number Diff line change
Expand Up @@ -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 applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.",
"types" : [ {
"type" : "enum",
"name" : "AorB",
"symbols" : ["A", "B"],
"default" : "A"
}, {
"type" : "enum",
"name" : "Position",
"namespace" : "avro.examples.baseball",
Expand Down Expand Up @@ -111,7 +116,10 @@
"response" : "null"
},
"bar" : {
"request" : [ ],
"request" : [ {
"name" : "choice",
"type" : "AorB"
} ],
"response" : "null"
},
"bazm" : {
Expand Down
11 changes: 10 additions & 1 deletion lang/java/compiler/src/test/idl/output/nestedimport.avpr
Original file line number Diff line number Diff line change
Expand Up @@ -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 applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.",
"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",
Expand Down Expand Up @@ -66,7 +72,10 @@
"response" : "null"
},
"bar" : {
"request" : [ ],
"request" : [ {
"name" : "choice",
"type" : "org.foo.AorB"
} ],
"response" : "null"
}
}
Expand Down

0 comments on commit b1517d3

Please sign in to comment.