Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for custom AvroTypeName annotation to allow overriding namespace when generating schema with reflection
  • Loading branch information
henryf1991 committed May 1, 2024
1 parent ab7ac6c commit cf77cba
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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
*
* https://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.avro.reflect;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Sets the avrotypename for this java type. When reading into this class, a
* reflectdatumreader looks for a schema field with the avrotypename.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface AvroTypeName {
String value() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -706,9 +706,7 @@ protected Schema createSchema(Type type, Map<String, Schema> names) {
AvroDoc annotatedDoc = c.getAnnotation(AvroDoc.class); // Docstring
String doc = (annotatedDoc != null) ? annotatedDoc.value() : null;
String name = c.getSimpleName();
String space = c.getPackage() == null ? "" : c.getPackage().getName();
if (c.getEnclosingClass() != null) // nested class
space = c.getEnclosingClass().getName().replace('$', '.');
String space = getNamespace(c);
Union union = c.getAnnotation(Union.class);
if (union != null) { // union annotated
return getAnnotatedUnion(union, names);
Expand Down Expand Up @@ -802,6 +800,21 @@ private String simpleName(Class<?> c) {
return simpleName;
}

/*
* Function checks if there is @AvroTypeName annotation on the class. If present
* then returns the value of the annotation else returns the package of the
* class
*/
private String getNamespace(Class<?> c) {
AvroTypeName avroTypeName = c.getAnnotation(AvroTypeName.class);
if (avroTypeName != null) {
return avroTypeName.value();
}
if (c.getEnclosingClass() != null) // nested class
return c.getEnclosingClass().getName().replace('$', '.');
return c.getPackage() == null ? "" : c.getPackage().getName();
}

private static final Schema THROWABLE_MESSAGE = makeNullable(Schema.create(Schema.Type.STRING));

// if array element type is a class with a union annotation, note it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@
<p> The {@link org.apache.avro.reflect.AvroName AvroName} annotation renames
the field in the schema to the given name. The reflect datum reader will look
for a schema field with the given name, when trying to read into such an
annotated java field.
annotated java field.

<p> The {@link org.apache.avro.reflect.AvroTypeName AvroTypeName} annotation renames
the namespace in the schema to the given namespace.

<p>The {@link org.apache.avro.reflect.AvroMeta AvroMeta} annotation adds an
arbitrary key:value pair in the schema at the node of the java field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1415,4 +1415,24 @@ void avroDoc() {
+ "{\"name\":\"foo\",\"type\":\"int\",\"doc\":\"Some Documentation\"}" + "]}");
}

@AvroTypeName("org.apache.avro.reflect.OverrideNamespace")
private static class NamespaceTest {

@AvroTypeName("org.apache.avro.reflect.InnerOverrideNamespace")
private static class InnerNamespaceTest {
}
}

@Test
void avroOverrideNamespaceTest() {
check(NamespaceTest.class,
"{\"type\":\"record\",\"name\":\"NamespaceTest\",\"namespace\":\"org.apache.avro.reflect.OverrideNamespace\",\"fields\":[]}");
}

@Test
void avroOverrideInnerNamespaceTest() {
check(NamespaceTest.InnerNamespaceTest.class,
"{\"type\":\"record\",\"name\":\"InnerNamespaceTest\",\"namespace\":\"org.apache.avro.reflect.InnerOverrideNamespace\",\"fields\":[]}");
}

}

0 comments on commit cf77cba

Please sign in to comment.