diff --git a/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializer.java b/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializer.java index d73bd2832..7c8b58129 100644 --- a/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializer.java +++ b/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializer.java @@ -9,8 +9,9 @@ */ package io.pravega.schemaregistry.serializer.avro.impl; -import com.google.common.base.Charsets; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; import io.pravega.schemaregistry.client.SchemaRegistryClient; import io.pravega.schemaregistry.contract.data.SchemaInfo; @@ -19,6 +20,7 @@ import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; import org.apache.avro.Schema; import org.apache.avro.io.BinaryDecoder; +import org.apache.avro.io.DatumReader; import org.apache.avro.io.DecoderFactory; import org.apache.avro.reflect.ReflectDatumReader; import org.apache.avro.specific.SpecificDatumReader; @@ -26,41 +28,51 @@ import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; import java.util.concurrent.ConcurrentHashMap; class AvroDeserializer extends AbstractDeserializer { - private final AvroSchema avroSchema; - private final ConcurrentHashMap knownSchemas; + private final ConcurrentHashMap> knownSchemaReaders; + private final boolean specific; + private final Schema readerSchema; AvroDeserializer(String groupId, SchemaRegistryClient client, AvroSchema schema, SerializerConfig.Decoders decoder, EncodingCache encodingCache) { super(groupId, client, schema, false, decoder, encodingCache, true); Preconditions.checkNotNull(schema); - this.avroSchema = schema; - this.knownSchemas = new ConcurrentHashMap<>(); + this.knownSchemaReaders = new ConcurrentHashMap<>(); + specific = SpecificRecordBase.class.isAssignableFrom(schema.getTClass()); + readerSchema = schema.getSchema(); + ByteBuffer schemaData = schema.getSchemaInfo().getSchemaData(); + knownSchemaReaders.put(schemaData, createDatumReader(readerSchema, readerSchema, specific)); } @Override public final T deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { Preconditions.checkNotNull(writerSchemaInfo); - Schema writerSchema; - if (knownSchemas.containsKey(writerSchemaInfo)) { - writerSchema = knownSchemas.get(writerSchemaInfo); - } else { - String schemaString = new String(writerSchemaInfo.getSchemaData().array(), Charsets.UTF_8); - writerSchema = new Schema.Parser().parse(schemaString); - knownSchemas.put(writerSchemaInfo, writerSchema); - } - Schema readerSchema = avroSchema.getSchema(); + final ByteBuffer writerSchemaData = writerSchemaInfo.getSchemaData(); + DatumReader datumReader = knownSchemaReaders.computeIfAbsent(writerSchemaData, key -> { + Schema writerSchema = AvroSchema.from(writerSchemaInfo).getSchema(); + return createDatumReader(writerSchema, this.readerSchema, specific); + }); BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(inputStream, null); - - if (SpecificRecordBase.class.isAssignableFrom(avroSchema.getTClass())) { - SpecificDatumReader datumReader = new SpecificDatumReader<>(writerSchema, readerSchema); - return datumReader.read(null, decoder); + return datumReader.read(null, decoder); + } + + @VisibleForTesting + DatumReader createDatumReader(Schema writerSchema, Schema readerSchema, boolean specific) { + DatumReader datumReader; + if (specific) { + datumReader = new SpecificDatumReader<>(writerSchema, readerSchema); } else { - ReflectDatumReader datumReader = new ReflectDatumReader<>(writerSchema, readerSchema); - return datumReader.read(null, decoder); + datumReader = new ReflectDatumReader<>(writerSchema, readerSchema); } + return datumReader; + } + + @VisibleForTesting + ImmutableMap> getKnownSchemaReaders() { + return ImmutableMap.copyOf(knownSchemaReaders); } } diff --git a/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroGenericDeserializer.java b/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroGenericDeserializer.java index 5cd0e23ca..21c28d531 100644 --- a/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroGenericDeserializer.java +++ b/serializers/avro/src/main/java/io/pravega/schemaregistry/serializer/avro/impl/AvroGenericDeserializer.java @@ -9,10 +9,12 @@ */ package io.pravega.schemaregistry.serializer.avro.impl; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; -import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; +import com.google.common.collect.ImmutableMap; import io.pravega.schemaregistry.client.SchemaRegistryClient; import io.pravega.schemaregistry.contract.data.SchemaInfo; +import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; import io.pravega.schemaregistry.serializer.shared.impl.AbstractDeserializer; import io.pravega.schemaregistry.serializer.shared.impl.EncodingCache; import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; @@ -20,30 +22,36 @@ import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.io.BinaryDecoder; import org.apache.avro.io.DecoderFactory; - +import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ConcurrentHashMap; public class AvroGenericDeserializer extends AbstractDeserializer { - private final ConcurrentHashMap knownSchemas; + private final ConcurrentHashMap, GenericDatumReader> knownSchemaReaders; public AvroGenericDeserializer(String groupId, SchemaRegistryClient client, @Nullable AvroSchema schema, SerializerConfig.Decoders decoder, EncodingCache encodingCache) { super(groupId, client, schema, false, decoder, encodingCache, true); - this.knownSchemas = new ConcurrentHashMap<>(); + this.knownSchemaReaders = new ConcurrentHashMap<>(); } @Override public final Object deserialize(InputStream inputStream, SchemaInfo writerSchemaInfo, SchemaInfo readerSchemaInfo) throws IOException { Preconditions.checkNotNull(writerSchemaInfo); - Schema writerSchema = knownSchemas.computeIfAbsent(writerSchemaInfo, x -> AvroSchema.from(x).getSchema()); - Schema readerSchema = knownSchemas.computeIfAbsent(readerSchemaInfo, x -> AvroSchema.from(x).getSchema()); - - GenericDatumReader genericDatumReader = new GenericDatumReader<>(writerSchema, readerSchema); - + final Pair keyPair = Pair.of(writerSchemaInfo, readerSchemaInfo); + GenericDatumReader genericDatumReader = knownSchemaReaders.computeIfAbsent(keyPair, key -> { + Schema writerSchema = AvroSchema.from(writerSchemaInfo).getSchema(); + Schema readerSchema = AvroSchema.from(readerSchemaInfo).getSchema(); + return new GenericDatumReader<>(writerSchema, readerSchema); + }); BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(inputStream, null); return genericDatumReader.read(null, decoder); } + + @VisibleForTesting + ImmutableMap, GenericDatumReader> getKnownSchemaReaders() { + return ImmutableMap.copyOf(knownSchemaReaders); + } } diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializerTest.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializerTest.java new file mode 100644 index 000000000..da14a34ee --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/AvroDeserializerTest.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. + * + * Licensed 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 + */ +package io.pravega.schemaregistry.serializer.avro.impl; + +import com.google.common.collect.ImmutableMap; +import io.pravega.client.stream.Serializer; +import io.pravega.schemaregistry.client.SchemaRegistryClient; +import io.pravega.schemaregistry.contract.data.*; +import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; +import io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro.AddressEntry; +import io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro.User; +import io.pravega.schemaregistry.serializer.shared.codec.Codecs; +import io.pravega.schemaregistry.serializer.shared.impl.SerializerConfig; +import lombok.extern.slf4j.Slf4j; +import org.apache.avro.generic.GenericDatumReader; +import org.apache.avro.io.DatumReader; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +@Slf4j +public class AvroDeserializerTest { + + private Serializer serializer; + private AvroDeserializer avroDeserializer; + private AvroGenericDeserializer genericDeserializer; + private User user; + + @Before + public void init() { + AvroSchema userAvroSchema = AvroSchema.of(User.class); + log.info("Aliases: {}", userAvroSchema.getSchema().getAliases()); + VersionInfo versionInfo1 = new VersionInfo("avroUser1", 0, 0); + SchemaRegistryClient client = mock(SchemaRegistryClient.class); + doAnswer(x -> true).when(client).canReadUsing(anyString(), any()); + doAnswer(x -> new EncodingId(0)).when(client).getEncodingId(anyString(), any(), any()); + doAnswer(x -> new EncodingInfo(versionInfo1, userAvroSchema.getSchemaInfo(), Codecs.None.getCodec().getCodecType())).when(client).getEncodingInfo(anyString(), eq(new EncodingId(0))); + SerializerConfig serializerConfig = SerializerConfig.builder().registryClient(client).groupId("avroUser1") + .createGroup(SerializationFormat.Avro).registerSchema(true).build(); + this.serializer = AvroSerializerFactory + .serializer(serializerConfig, userAvroSchema); + this.avroDeserializer = Mockito.spy((AvroDeserializer)AvroSerializerFactory.deserializer( + serializerConfig, userAvroSchema)); + + org.apache.avro.Schema schema = userAvroSchema.getSchema(); + AvroSchema objectAvroSchema = AvroSchema.of(schema); + this.genericDeserializer = Mockito.spy((AvroGenericDeserializer)AvroSerializerFactory.genericDeserializer( + serializerConfig, objectAvroSchema)); + + this.user = User.newBuilder() + .setUserId("111111111111") + .setBiography("Greg Egan was born 20 August 1961") + .setName("Greg Egan") + .setEventTimestamp(System.currentTimeMillis()) + .setKeyValues(null) + .setKeyValues2(null) + .setKeyValues3(null) + .setAddress(AddressEntry.newBuilder().setCity("Perth") + .setPostalCode(5018) + .setStreetAddress("4/19 Gardner Road").build()).build(); + } + + @Test + public void testCreatingReadersOnceForSchemaGeneric() { + ImmutableMap, GenericDatumReader> knownSchemaReaders1 = genericDeserializer.getKnownSchemaReaders(); + Assert.assertTrue(knownSchemaReaders1.isEmpty()); + Assert.assertEquals(0, knownSchemaReaders1.size()); + + ByteBuffer serialized = serializer.serialize(user); + int payloadSize = serialized.limit(); + log.info("serialized into {}", payloadSize); + Assert.assertEquals(100, payloadSize); + byte[] bytes = serialized.array(); + log.info("bytes: {}", new String(bytes, StandardCharsets.UTF_8)); + Object user1 = genericDeserializer.deserialize(ByteBuffer.wrap(bytes)); + log.info("deserialized {}", user1); + ImmutableMap, GenericDatumReader> knownSchemaReaders2 = genericDeserializer.getKnownSchemaReaders(); + Assert.assertEquals(1, knownSchemaReaders2.size()); + } + + @Test + public void testCreatingReadersOnceForSchema() { + ImmutableMap> knownSchemaReaders1 = avroDeserializer.getKnownSchemaReaders(); + Assert.assertFalse(knownSchemaReaders1.isEmpty()); + Assert.assertEquals(1, knownSchemaReaders1.size()); + AvroSchema userAvroSchema = AvroSchema.of(User.class); + DatumReader datumReader = knownSchemaReaders1.get(userAvroSchema.getSchemaInfo().getSchemaData()); + Assert.assertNotNull(datumReader); + + ByteBuffer serialized = serializer.serialize(user); + int payloadSize = serialized.limit(); + log.info("serialized into {}", payloadSize); + Assert.assertEquals(100, payloadSize); + byte[] bytes = serialized.array(); + log.info("bytes: {}", new String(bytes, StandardCharsets.UTF_8)); + User user1 = avroDeserializer.deserialize(ByteBuffer.wrap(bytes)); + + log.info("deserialized {}", user1); + Assert.assertEquals(user, user1); + serializer.serialize(user1); + ImmutableMap> knownSchemaReaders2 = avroDeserializer.getKnownSchemaReaders(); + Assert.assertEquals(1, knownSchemaReaders2.size()); + Assert.assertEquals(knownSchemaReaders1, knownSchemaReaders2); + // called zero times outside constructor + Mockito.verify(avroDeserializer, Mockito.times(0)).createDatumReader(Mockito.any(), Mockito.any(), Mockito.anyBoolean()); + } + +} diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/SerializerTest.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/SerializerTest.java index a3ea83379..759d03dda 100644 --- a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/SerializerTest.java +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/impl/SerializerTest.java @@ -9,6 +9,7 @@ */ package io.pravega.schemaregistry.serializer.avro.impl; + import io.pravega.client.stream.Serializer; import io.pravega.schemaregistry.serializer.avro.schemas.AvroSchema; import io.pravega.schemaregistry.client.SchemaRegistryClient; diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/EventTimestampAware.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/EventTimestampAware.java new file mode 100644 index 000000000..1f8a6dd5c --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/EventTimestampAware.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) Dell Inc., or its subsidiaries. All Rights Reserved. + * + * Licensed 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 + */ +package io.pravega.schemaregistry.serializer.avro.testobjs; + +public interface EventTimestampAware { + void setEventTimestamp(Long value); + + Long getEventTimestamp(); +} diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/AddressEntry.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/AddressEntry.java new file mode 100644 index 000000000..bc5c0ae28 --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/AddressEntry.java @@ -0,0 +1,494 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro; + +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.SchemaStore; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; + +@org.apache.avro.specific.AvroGenerated +public class AddressEntry extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 3877146114645745535L; + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AddressEntry\",\"namespace\":\"io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro\",\"fields\":[{\"name\":\"streetAddress\",\"type\":\"string\"},{\"name\":\"postalCode\",\"type\":[\"null\",\"int\"],\"default\":null},{\"name\":\"city\",\"type\":\"string\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this AddressEntry to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a AddressEntry from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a AddressEntry instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static AddressEntry fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + @Deprecated + public CharSequence streetAddress; + @Deprecated + public Integer postalCode; + @Deprecated + public CharSequence city; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public AddressEntry() {} + + /** + * All-args constructor. + * @param streetAddress The new value for streetAddress + * @param postalCode The new value for postalCode + * @param city The new value for city + */ + public AddressEntry(CharSequence streetAddress, Integer postalCode, CharSequence city) { + this.streetAddress = streetAddress; + this.postalCode = postalCode; + this.city = city; + } + + public SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public Object get(int field$) { + switch (field$) { + case 0: return streetAddress; + case 1: return postalCode; + case 2: return city; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, Object value$) { + switch (field$) { + case 0: streetAddress = (CharSequence)value$; break; + case 1: postalCode = (Integer)value$; break; + case 2: city = (CharSequence)value$; break; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'streetAddress' field. + * @return The value of the 'streetAddress' field. + */ + public CharSequence getStreetAddress() { + return streetAddress; + } + + + /** + * Sets the value of the 'streetAddress' field. + * @param value the value to set. + */ + public void setStreetAddress(CharSequence value) { + this.streetAddress = value; + } + + /** + * Gets the value of the 'postalCode' field. + * @return The value of the 'postalCode' field. + */ + public Integer getPostalCode() { + return postalCode; + } + + + /** + * Sets the value of the 'postalCode' field. + * @param value the value to set. + */ + public void setPostalCode(Integer value) { + this.postalCode = value; + } + + /** + * Gets the value of the 'city' field. + * @return The value of the 'city' field. + */ + public CharSequence getCity() { + return city; + } + + + /** + * Sets the value of the 'city' field. + * @param value the value to set. + */ + public void setCity(CharSequence value) { + this.city = value; + } + + /** + * Creates a new AddressEntry RecordBuilder. + * @return A new AddressEntry RecordBuilder + */ + public static AddressEntry.Builder newBuilder() { + return new AddressEntry.Builder(); + } + + /** + * Creates a new AddressEntry RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new AddressEntry RecordBuilder + */ + public static AddressEntry.Builder newBuilder(AddressEntry.Builder other) { + if (other == null) { + return new AddressEntry.Builder(); + } else { + return new AddressEntry.Builder(other); + } + } + + /** + * Creates a new AddressEntry RecordBuilder by copying an existing AddressEntry instance. + * @param other The existing instance to copy. + * @return A new AddressEntry RecordBuilder + */ + public static AddressEntry.Builder newBuilder(AddressEntry other) { + if (other == null) { + return new AddressEntry.Builder(); + } else { + return new AddressEntry.Builder(other); + } + } + + /** + * RecordBuilder for AddressEntry instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private CharSequence streetAddress; + private Integer postalCode; + private CharSequence city; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(AddressEntry.Builder other) { + super(other); + if (isValidValue(fields()[0], other.streetAddress)) { + this.streetAddress = data().deepCopy(fields()[0].schema(), other.streetAddress); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.postalCode)) { + this.postalCode = data().deepCopy(fields()[1].schema(), other.postalCode); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.city)) { + this.city = data().deepCopy(fields()[2].schema(), other.city); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + } + + /** + * Creates a Builder by copying an existing AddressEntry instance + * @param other The existing instance to copy. + */ + private Builder(AddressEntry other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.streetAddress)) { + this.streetAddress = data().deepCopy(fields()[0].schema(), other.streetAddress); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.postalCode)) { + this.postalCode = data().deepCopy(fields()[1].schema(), other.postalCode); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.city)) { + this.city = data().deepCopy(fields()[2].schema(), other.city); + fieldSetFlags()[2] = true; + } + } + + /** + * Gets the value of the 'streetAddress' field. + * @return The value. + */ + public CharSequence getStreetAddress() { + return streetAddress; + } + + + /** + * Sets the value of the 'streetAddress' field. + * @param value The value of 'streetAddress'. + * @return This builder. + */ + public AddressEntry.Builder setStreetAddress(CharSequence value) { + validate(fields()[0], value); + this.streetAddress = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'streetAddress' field has been set. + * @return True if the 'streetAddress' field has been set, false otherwise. + */ + public boolean hasStreetAddress() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'streetAddress' field. + * @return This builder. + */ + public AddressEntry.Builder clearStreetAddress() { + streetAddress = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'postalCode' field. + * @return The value. + */ + public Integer getPostalCode() { + return postalCode; + } + + + /** + * Sets the value of the 'postalCode' field. + * @param value The value of 'postalCode'. + * @return This builder. + */ + public AddressEntry.Builder setPostalCode(Integer value) { + validate(fields()[1], value); + this.postalCode = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'postalCode' field has been set. + * @return True if the 'postalCode' field has been set, false otherwise. + */ + public boolean hasPostalCode() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'postalCode' field. + * @return This builder. + */ + public AddressEntry.Builder clearPostalCode() { + postalCode = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'city' field. + * @return The value. + */ + public CharSequence getCity() { + return city; + } + + + /** + * Sets the value of the 'city' field. + * @param value The value of 'city'. + * @return This builder. + */ + public AddressEntry.Builder setCity(CharSequence value) { + validate(fields()[2], value); + this.city = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'city' field has been set. + * @return True if the 'city' field has been set, false otherwise. + */ + public boolean hasCity() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'city' field. + * @return This builder. + */ + public AddressEntry.Builder clearCity() { + city = null; + fieldSetFlags()[2] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public AddressEntry build() { + try { + AddressEntry record = new AddressEntry(); + record.streetAddress = fieldSetFlags()[0] ? this.streetAddress : (CharSequence) defaultValue(fields()[0]); + record.postalCode = fieldSetFlags()[1] ? this.postalCode : (Integer) defaultValue(fields()[1]); + record.city = fieldSetFlags()[2] ? this.city : (CharSequence) defaultValue(fields()[2]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override + public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override + public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override + protected boolean hasCustomCoders() { return true; } + + @Override + public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.streetAddress); + + if (this.postalCode == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + out.writeInt(this.postalCode); + } + + out.writeString(this.city); + + } + + @Override + public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.streetAddress = in.readString(this.streetAddress instanceof Utf8 ? (Utf8)this.streetAddress : null); + + if (in.readIndex() != 1) { + in.readNull(); + this.postalCode = null; + } else { + this.postalCode = in.readInt(); + } + + this.city = in.readString(this.city instanceof Utf8 ? (Utf8)this.city : null); + + } else { + for (int i = 0; i < 3; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.streetAddress = in.readString(this.streetAddress instanceof Utf8 ? (Utf8)this.streetAddress : null); + break; + + case 1: + if (in.readIndex() != 1) { + in.readNull(); + this.postalCode = null; + } else { + this.postalCode = in.readInt(); + } + break; + + case 2: + this.city = in.readString(this.city instanceof Utf8 ? (Utf8)this.city : null); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue.java new file mode 100644 index 000000000..24dfacd7c --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue.java @@ -0,0 +1,391 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class KeyValue extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 3877342106303931869L; + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"JSONKeyValue\",\"namespace\":\"io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this JSONKeyValue to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a JSONKeyValue from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a JSONKeyValue instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static KeyValue fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + @Deprecated public java.lang.CharSequence name; + @Deprecated public java.lang.CharSequence value; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public KeyValue() {} + + /** + * All-args constructor. + * @param name The new value for name + * @param value The new value for value + */ + public KeyValue(java.lang.CharSequence name, java.lang.CharSequence value) { + this.name = name; + this.value = value; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return name; + case 1: return value; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: name = (java.lang.CharSequence)value$; break; + case 1: value = (java.lang.CharSequence)value$; break; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(java.lang.CharSequence value) { + this.name = value; + } + + /** + * Gets the value of the 'value' field. + * @return The value of the 'value' field. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value the value to set. + */ + public void setValue(java.lang.CharSequence value) { + this.value = value; + } + + /** + * Creates a new JSONKeyValue RecordBuilder. + * @return A new JSONKeyValue RecordBuilder + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Creates a new JSONKeyValue RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new JSONKeyValue RecordBuilder + */ + public static Builder newBuilder( Builder other) { + if (other == null) { + return new Builder(); + } else { + return new Builder(other); + } + } + + /** + * Creates a new JSONKeyValue RecordBuilder by copying an existing JSONKeyValue instance. + * @param other The existing instance to copy. + * @return A new JSONKeyValue RecordBuilder + */ + public static Builder newBuilder( KeyValue other) { + if (other == null) { + return new Builder(); + } else { + return new Builder(other); + } + } + + /** + * RecordBuilder for JSONKeyValue instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private java.lang.CharSequence name; + private java.lang.CharSequence value; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder( Builder other) { + super(other); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + } + + /** + * Creates a Builder by copying an existing JSONKeyValue instance + * @param other The existing instance to copy. + */ + private Builder( KeyValue other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = true; + } + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public Builder setName(java.lang.CharSequence value) { + validate(fields()[0], value); + this.name = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public Builder clearName() { + name = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'value' field. + * @return The value. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value The value of 'value'. + * @return This builder. + */ + public Builder setValue(java.lang.CharSequence value) { + validate(fields()[1], value); + this.value = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'value' field has been set. + * @return True if the 'value' field has been set, false otherwise. + */ + public boolean hasValue() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'value' field. + * @return This builder. + */ + public Builder clearValue() { + value = null; + fieldSetFlags()[1] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public KeyValue build() { + try { + KeyValue record = new KeyValue(); + record.name = fieldSetFlags()[0] ? this.name : (java.lang.CharSequence) defaultValue(fields()[0]); + record.value = fieldSetFlags()[1] ? this.value : (java.lang.CharSequence) defaultValue(fields()[1]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.name); + + out.writeString(this.value); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + + } else { + for (int i = 0; i < 2; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + break; + + case 1: + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue2.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue2.java new file mode 100644 index 000000000..76d59a4ea --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue2.java @@ -0,0 +1,391 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class KeyValue2 extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -2087383047577309025L; + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"KeyValue2\",\"namespace\":\"io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this KeyValue2 to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a KeyValue2 from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a KeyValue2 instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static KeyValue2 fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + @Deprecated public java.lang.CharSequence name; + @Deprecated public java.lang.CharSequence value; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public KeyValue2() {} + + /** + * All-args constructor. + * @param name The new value for name + * @param value The new value for value + */ + public KeyValue2(java.lang.CharSequence name, java.lang.CharSequence value) { + this.name = name; + this.value = value; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return name; + case 1: return value; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: name = (java.lang.CharSequence)value$; break; + case 1: value = (java.lang.CharSequence)value$; break; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(java.lang.CharSequence value) { + this.name = value; + } + + /** + * Gets the value of the 'value' field. + * @return The value of the 'value' field. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value the value to set. + */ + public void setValue(java.lang.CharSequence value) { + this.value = value; + } + + /** + * Creates a new KeyValue2 RecordBuilder. + * @return A new KeyValue2 RecordBuilder + */ + public static KeyValue2.Builder newBuilder() { + return new KeyValue2.Builder(); + } + + /** + * Creates a new KeyValue2 RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new KeyValue2 RecordBuilder + */ + public static KeyValue2.Builder newBuilder(KeyValue2.Builder other) { + if (other == null) { + return new KeyValue2.Builder(); + } else { + return new KeyValue2.Builder(other); + } + } + + /** + * Creates a new KeyValue2 RecordBuilder by copying an existing KeyValue2 instance. + * @param other The existing instance to copy. + * @return A new KeyValue2 RecordBuilder + */ + public static KeyValue2.Builder newBuilder(KeyValue2 other) { + if (other == null) { + return new KeyValue2.Builder(); + } else { + return new KeyValue2.Builder(other); + } + } + + /** + * RecordBuilder for KeyValue2 instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private java.lang.CharSequence name; + private java.lang.CharSequence value; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(KeyValue2.Builder other) { + super(other); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + } + + /** + * Creates a Builder by copying an existing KeyValue2 instance + * @param other The existing instance to copy. + */ + private Builder(KeyValue2 other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = true; + } + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public KeyValue2.Builder setName(java.lang.CharSequence value) { + validate(fields()[0], value); + this.name = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public KeyValue2.Builder clearName() { + name = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'value' field. + * @return The value. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value The value of 'value'. + * @return This builder. + */ + public KeyValue2.Builder setValue(java.lang.CharSequence value) { + validate(fields()[1], value); + this.value = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'value' field has been set. + * @return True if the 'value' field has been set, false otherwise. + */ + public boolean hasValue() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'value' field. + * @return This builder. + */ + public KeyValue2.Builder clearValue() { + value = null; + fieldSetFlags()[1] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public KeyValue2 build() { + try { + KeyValue2 record = new KeyValue2(); + record.name = fieldSetFlags()[0] ? this.name : (java.lang.CharSequence) defaultValue(fields()[0]); + record.value = fieldSetFlags()[1] ? this.value : (java.lang.CharSequence) defaultValue(fields()[1]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.name); + + out.writeString(this.value); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + + } else { + for (int i = 0; i < 2; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + break; + + case 1: + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue3.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue3.java new file mode 100644 index 000000000..9c58b323a --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/KeyValue3.java @@ -0,0 +1,391 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class KeyValue3 extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 5188010898989221497L; + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"KeyValue3\",\"namespace\":\"io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this KeyValue3 to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a KeyValue3 from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a KeyValue3 instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static KeyValue3 fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + @Deprecated public java.lang.CharSequence name; + @Deprecated public java.lang.CharSequence value; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public KeyValue3() {} + + /** + * All-args constructor. + * @param name The new value for name + * @param value The new value for value + */ + public KeyValue3(java.lang.CharSequence name, java.lang.CharSequence value) { + this.name = name; + this.value = value; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return name; + case 1: return value; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: name = (java.lang.CharSequence)value$; break; + case 1: value = (java.lang.CharSequence)value$; break; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(java.lang.CharSequence value) { + this.name = value; + } + + /** + * Gets the value of the 'value' field. + * @return The value of the 'value' field. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value the value to set. + */ + public void setValue(java.lang.CharSequence value) { + this.value = value; + } + + /** + * Creates a new KeyValue3 RecordBuilder. + * @return A new KeyValue3 RecordBuilder + */ + public static KeyValue3.Builder newBuilder() { + return new KeyValue3.Builder(); + } + + /** + * Creates a new KeyValue3 RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new KeyValue3 RecordBuilder + */ + public static KeyValue3.Builder newBuilder(KeyValue3.Builder other) { + if (other == null) { + return new KeyValue3.Builder(); + } else { + return new KeyValue3.Builder(other); + } + } + + /** + * Creates a new KeyValue3 RecordBuilder by copying an existing KeyValue3 instance. + * @param other The existing instance to copy. + * @return A new KeyValue3 RecordBuilder + */ + public static KeyValue3.Builder newBuilder(KeyValue3 other) { + if (other == null) { + return new KeyValue3.Builder(); + } else { + return new KeyValue3.Builder(other); + } + } + + /** + * RecordBuilder for KeyValue3 instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private java.lang.CharSequence name; + private java.lang.CharSequence value; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(KeyValue3.Builder other) { + super(other); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + } + + /** + * Creates a Builder by copying an existing KeyValue3 instance + * @param other The existing instance to copy. + */ + private Builder(KeyValue3 other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.value)) { + this.value = data().deepCopy(fields()[1].schema(), other.value); + fieldSetFlags()[1] = true; + } + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public java.lang.CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public KeyValue3.Builder setName(java.lang.CharSequence value) { + validate(fields()[0], value); + this.name = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public KeyValue3.Builder clearName() { + name = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'value' field. + * @return The value. + */ + public java.lang.CharSequence getValue() { + return value; + } + + + /** + * Sets the value of the 'value' field. + * @param value The value of 'value'. + * @return This builder. + */ + public KeyValue3.Builder setValue(java.lang.CharSequence value) { + validate(fields()[1], value); + this.value = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'value' field has been set. + * @return True if the 'value' field has been set, false otherwise. + */ + public boolean hasValue() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'value' field. + * @return This builder. + */ + public KeyValue3.Builder clearValue() { + value = null; + fieldSetFlags()[1] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public KeyValue3 build() { + try { + KeyValue3 record = new KeyValue3(); + record.name = fieldSetFlags()[0] ? this.name : (java.lang.CharSequence) defaultValue(fields()[0]); + record.value = fieldSetFlags()[1] ? this.value : (java.lang.CharSequence) defaultValue(fields()[1]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.name); + + out.writeString(this.value); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + + } else { + for (int i = 0; i < 2; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + break; + + case 1: + this.value = in.readString(this.value instanceof Utf8 ? (Utf8)this.value : null); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/User.java b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/User.java new file mode 100644 index 000000000..089b52879 --- /dev/null +++ b/serializers/avro/src/test/java/io/pravega/schemaregistry/serializer/avro/testobjs/generated/avro/User.java @@ -0,0 +1,1148 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro; + +import io.pravega.schemaregistry.serializer.avro.testobjs.EventTimestampAware; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.SchemaStore; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; + +@org.apache.avro.specific.AvroGenerated +public class User extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord, EventTimestampAware { + private static final long serialVersionUID = 7820250504031892698L; + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"io.pravega.schemaregistry.serializer.avro.testobjs.generated.avro\",\"fields\":[{\"name\":\"userId\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"biography\",\"type\":[\"null\",\"string\"],\"default\":null},{\"name\":\"eventTimestamp\",\"type\":[\"null\",\"long\"],\"default\":null},{\"name\":\"keyValues\",\"type\":[\"null\",{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"KeyValue\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}}]},{\"name\":\"keyValues2\",\"type\":[\"null\",{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"KeyValue2\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}}]},{\"name\":\"keyValues3\",\"type\":[\"null\",{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"KeyValue3\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}]}}]},{\"name\":\"address\",\"type\":{\"type\":\"record\",\"name\":\"AddressEntry\",\"fields\":[{\"name\":\"streetAddress\",\"type\":\"string\"},{\"name\":\"postalCode\",\"type\":[\"null\",\"int\"],\"default\":null},{\"name\":\"city\",\"type\":\"string\"}]}}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this User to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a User from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a User instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static User fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + @Deprecated + public CharSequence userId; + @Deprecated + public CharSequence name; + @Deprecated + public CharSequence biography; + @Deprecated + public Long eventTimestamp; + @Deprecated + public java.util.List keyValues; + @Deprecated + public java.util.List keyValues2; + @Deprecated + public java.util.List keyValues3; + @Deprecated + public AddressEntry address; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public User() {} + + /** + * All-args constructor. + * @param userId The new value for userId + * @param name The new value for name + * @param biography The new value for biography + * @param eventTimestamp The new value for eventTimestamp + * @param keyValues The new value for keyValues + * @param keyValues2 The new value for keyValues2 + * @param keyValues3 The new value for keyValues3 + * @param address The new value for address + */ + public User(CharSequence userId, CharSequence name, CharSequence biography, Long eventTimestamp, java.util.List keyValues, java.util.List keyValues2, java.util.List keyValues3, AddressEntry address) { + this.userId = userId; + this.name = name; + this.biography = biography; + this.eventTimestamp = eventTimestamp; + this.keyValues = keyValues; + this.keyValues2 = keyValues2; + this.keyValues3 = keyValues3; + this.address = address; + } + + public SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public Object get(int field$) { + switch (field$) { + case 0: return userId; + case 1: return name; + case 2: return biography; + case 3: return eventTimestamp; + case 4: return keyValues; + case 5: return keyValues2; + case 6: return keyValues3; + case 7: return address; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, Object value$) { + switch (field$) { + case 0: userId = (CharSequence)value$; break; + case 1: name = (CharSequence)value$; break; + case 2: biography = (CharSequence)value$; break; + case 3: eventTimestamp = (Long)value$; break; + case 4: keyValues = (java.util.List)value$; break; + case 5: keyValues2 = (java.util.List)value$; break; + case 6: keyValues3 = (java.util.List)value$; break; + case 7: address = (AddressEntry)value$; break; + default: throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'userId' field. + * @return The value of the 'userId' field. + */ + public CharSequence getUserId() { + return userId; + } + + + /** + * Sets the value of the 'userId' field. + * @param value the value to set. + */ + public void setUserId(CharSequence value) { + this.userId = value; + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(CharSequence value) { + this.name = value; + } + + /** + * Gets the value of the 'biography' field. + * @return The value of the 'biography' field. + */ + public CharSequence getBiography() { + return biography; + } + + + /** + * Sets the value of the 'biography' field. + * @param value the value to set. + */ + public void setBiography(CharSequence value) { + this.biography = value; + } + + /** + * Gets the value of the 'eventTimestamp' field. + * @return The value of the 'eventTimestamp' field. + */ + public Long getEventTimestamp() { + return eventTimestamp; + } + + + /** + * Sets the value of the 'eventTimestamp' field. + * @param value the value to set. + */ + public void setEventTimestamp(Long value) { + this.eventTimestamp = value; + } + + /** + * Gets the value of the 'keyValues' field. + * @return The value of the 'keyValues' field. + */ + public java.util.List getKeyValues() { + return keyValues; + } + + + /** + * Sets the value of the 'keyValues' field. + * @param value the value to set. + */ + public void setKeyValues(java.util.List value) { + this.keyValues = value; + } + + /** + * Gets the value of the 'keyValues2' field. + * @return The value of the 'keyValues2' field. + */ + public java.util.List getKeyValues2() { + return keyValues2; + } + + + /** + * Sets the value of the 'keyValues2' field. + * @param value the value to set. + */ + public void setKeyValues2(java.util.List value) { + this.keyValues2 = value; + } + + /** + * Gets the value of the 'keyValues3' field. + * @return The value of the 'keyValues3' field. + */ + public java.util.List getKeyValues3() { + return keyValues3; + } + + + /** + * Sets the value of the 'keyValues3' field. + * @param value the value to set. + */ + public void setKeyValues3(java.util.List value) { + this.keyValues3 = value; + } + + /** + * Gets the value of the 'address' field. + * @return The value of the 'address' field. + */ + public AddressEntry getAddress() { + return address; + } + + + /** + * Sets the value of the 'address' field. + * @param value the value to set. + */ + public void setAddress(AddressEntry value) { + this.address = value; + } + + /** + * Creates a new User RecordBuilder. + * @return A new User RecordBuilder + */ + public static User.Builder newBuilder() { + return new User.Builder(); + } + + /** + * Creates a new User RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new User RecordBuilder + */ + public static User.Builder newBuilder(User.Builder other) { + if (other == null) { + return new User.Builder(); + } else { + return new User.Builder(other); + } + } + + /** + * Creates a new User RecordBuilder by copying an existing User instance. + * @param other The existing instance to copy. + * @return A new User RecordBuilder + */ + public static User.Builder newBuilder(User other) { + if (other == null) { + return new User.Builder(); + } else { + return new User.Builder(other); + } + } + + /** + * RecordBuilder for User instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private CharSequence userId; + private CharSequence name; + private CharSequence biography; + private Long eventTimestamp; + private java.util.List keyValues; + private java.util.List keyValues2; + private java.util.List keyValues3; + private AddressEntry address; + private AddressEntry.Builder addressBuilder; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(User.Builder other) { + super(other); + if (isValidValue(fields()[0], other.userId)) { + this.userId = data().deepCopy(fields()[0].schema(), other.userId); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.biography)) { + this.biography = data().deepCopy(fields()[2].schema(), other.biography); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.eventTimestamp)) { + this.eventTimestamp = data().deepCopy(fields()[3].schema(), other.eventTimestamp); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.keyValues)) { + this.keyValues = data().deepCopy(fields()[4].schema(), other.keyValues); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.keyValues2)) { + this.keyValues2 = data().deepCopy(fields()[5].schema(), other.keyValues2); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.keyValues3)) { + this.keyValues3 = data().deepCopy(fields()[6].schema(), other.keyValues3); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.address)) { + this.address = data().deepCopy(fields()[7].schema(), other.address); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (other.hasAddressBuilder()) { + this.addressBuilder = AddressEntry.newBuilder(other.getAddressBuilder()); + } + } + + /** + * Creates a Builder by copying an existing User instance + * @param other The existing instance to copy. + */ + private Builder(User other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.userId)) { + this.userId = data().deepCopy(fields()[0].schema(), other.userId); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.biography)) { + this.biography = data().deepCopy(fields()[2].schema(), other.biography); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.eventTimestamp)) { + this.eventTimestamp = data().deepCopy(fields()[3].schema(), other.eventTimestamp); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.keyValues)) { + this.keyValues = data().deepCopy(fields()[4].schema(), other.keyValues); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.keyValues2)) { + this.keyValues2 = data().deepCopy(fields()[5].schema(), other.keyValues2); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.keyValues3)) { + this.keyValues3 = data().deepCopy(fields()[6].schema(), other.keyValues3); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.address)) { + this.address = data().deepCopy(fields()[7].schema(), other.address); + fieldSetFlags()[7] = true; + } + this.addressBuilder = null; + } + + /** + * Gets the value of the 'userId' field. + * @return The value. + */ + public CharSequence getUserId() { + return userId; + } + + + /** + * Sets the value of the 'userId' field. + * @param value The value of 'userId'. + * @return This builder. + */ + public User.Builder setUserId(CharSequence value) { + validate(fields()[0], value); + this.userId = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'userId' field has been set. + * @return True if the 'userId' field has been set, false otherwise. + */ + public boolean hasUserId() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'userId' field. + * @return This builder. + */ + public User.Builder clearUserId() { + userId = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public CharSequence getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public User.Builder setName(CharSequence value) { + validate(fields()[1], value); + this.name = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public User.Builder clearName() { + name = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'biography' field. + * @return The value. + */ + public CharSequence getBiography() { + return biography; + } + + + /** + * Sets the value of the 'biography' field. + * @param value The value of 'biography'. + * @return This builder. + */ + public User.Builder setBiography(CharSequence value) { + validate(fields()[2], value); + this.biography = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'biography' field has been set. + * @return True if the 'biography' field has been set, false otherwise. + */ + public boolean hasBiography() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'biography' field. + * @return This builder. + */ + public User.Builder clearBiography() { + biography = null; + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'eventTimestamp' field. + * @return The value. + */ + public Long getEventTimestamp() { + return eventTimestamp; + } + + + /** + * Sets the value of the 'eventTimestamp' field. + * @param value The value of 'eventTimestamp'. + * @return This builder. + */ + public User.Builder setEventTimestamp(Long value) { + validate(fields()[3], value); + this.eventTimestamp = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'eventTimestamp' field has been set. + * @return True if the 'eventTimestamp' field has been set, false otherwise. + */ + public boolean hasEventTimestamp() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'eventTimestamp' field. + * @return This builder. + */ + public User.Builder clearEventTimestamp() { + eventTimestamp = null; + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'keyValues' field. + * @return The value. + */ + public java.util.List getKeyValues() { + return keyValues; + } + + + /** + * Sets the value of the 'keyValues' field. + * @param value The value of 'keyValues'. + * @return This builder. + */ + public User.Builder setKeyValues(java.util.List value) { + validate(fields()[4], value); + this.keyValues = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'keyValues' field has been set. + * @return True if the 'keyValues' field has been set, false otherwise. + */ + public boolean hasKeyValues() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'keyValues' field. + * @return This builder. + */ + public User.Builder clearKeyValues() { + keyValues = null; + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'keyValues2' field. + * @return The value. + */ + public java.util.List getKeyValues2() { + return keyValues2; + } + + + /** + * Sets the value of the 'keyValues2' field. + * @param value The value of 'keyValues2'. + * @return This builder. + */ + public User.Builder setKeyValues2(java.util.List value) { + validate(fields()[5], value); + this.keyValues2 = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'keyValues2' field has been set. + * @return True if the 'keyValues2' field has been set, false otherwise. + */ + public boolean hasKeyValues2() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'keyValues2' field. + * @return This builder. + */ + public User.Builder clearKeyValues2() { + keyValues2 = null; + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'keyValues3' field. + * @return The value. + */ + public java.util.List getKeyValues3() { + return keyValues3; + } + + + /** + * Sets the value of the 'keyValues3' field. + * @param value The value of 'keyValues3'. + * @return This builder. + */ + public User.Builder setKeyValues3(java.util.List value) { + validate(fields()[6], value); + this.keyValues3 = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'keyValues3' field has been set. + * @return True if the 'keyValues3' field has been set, false otherwise. + */ + public boolean hasKeyValues3() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'keyValues3' field. + * @return This builder. + */ + public User.Builder clearKeyValues3() { + keyValues3 = null; + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'address' field. + * @return The value. + */ + public AddressEntry getAddress() { + return address; + } + + + /** + * Sets the value of the 'address' field. + * @param value The value of 'address'. + * @return This builder. + */ + public User.Builder setAddress(AddressEntry value) { + validate(fields()[7], value); + this.addressBuilder = null; + this.address = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'address' field has been set. + * @return True if the 'address' field has been set, false otherwise. + */ + public boolean hasAddress() { + return fieldSetFlags()[7]; + } + + /** + * Gets the Builder instance for the 'address' field and creates one if it doesn't exist yet. + * @return This builder. + */ + public AddressEntry.Builder getAddressBuilder() { + if (addressBuilder == null) { + if (hasAddress()) { + setAddressBuilder(AddressEntry.newBuilder(address)); + } else { + setAddressBuilder(AddressEntry.newBuilder()); + } + } + return addressBuilder; + } + + /** + * Sets the Builder instance for the 'address' field + * @param value The builder instance that must be set. + * @return This builder. + */ + public User.Builder setAddressBuilder(AddressEntry.Builder value) { + clearAddress(); + addressBuilder = value; + return this; + } + + /** + * Checks whether the 'address' field has an active Builder instance + * @return True if the 'address' field has an active Builder instance + */ + public boolean hasAddressBuilder() { + return addressBuilder != null; + } + + /** + * Clears the value of the 'address' field. + * @return This builder. + */ + public User.Builder clearAddress() { + address = null; + addressBuilder = null; + fieldSetFlags()[7] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public User build() { + try { + User record = new User(); + record.userId = fieldSetFlags()[0] ? this.userId : (CharSequence) defaultValue(fields()[0]); + record.name = fieldSetFlags()[1] ? this.name : (CharSequence) defaultValue(fields()[1]); + record.biography = fieldSetFlags()[2] ? this.biography : (CharSequence) defaultValue(fields()[2]); + record.eventTimestamp = fieldSetFlags()[3] ? this.eventTimestamp : (Long) defaultValue(fields()[3]); + record.keyValues = fieldSetFlags()[4] ? this.keyValues : (java.util.List) defaultValue(fields()[4]); + record.keyValues2 = fieldSetFlags()[5] ? this.keyValues2 : (java.util.List) defaultValue(fields()[5]); + record.keyValues3 = fieldSetFlags()[6] ? this.keyValues3 : (java.util.List) defaultValue(fields()[6]); + if (addressBuilder != null) { + try { + record.address = this.addressBuilder.build(); + } catch (org.apache.avro.AvroMissingFieldException e) { + e.addParentField(record.getSchema().getField("address")); + throw e; + } + } else { + record.address = fieldSetFlags()[7] ? this.address : (AddressEntry) defaultValue(fields()[7]); + } + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override + public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override + public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override + protected boolean hasCustomCoders() { return true; } + + @Override + public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.userId); + + out.writeString(this.name); + + if (this.biography == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + out.writeString(this.biography); + } + + if (this.eventTimestamp == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + out.writeLong(this.eventTimestamp); + } + + if (this.keyValues == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + long size0 = this.keyValues.size(); + out.writeArrayStart(); + out.setItemCount(size0); + long actualSize0 = 0; + for (KeyValue e0: this.keyValues) { + actualSize0++; + out.startItem(); + e0.customEncode(out); + } + out.writeArrayEnd(); + if (actualSize0 != size0) + throw new java.util.ConcurrentModificationException("Array-size written was " + size0 + ", but element count was " + actualSize0 + "."); + } + + if (this.keyValues2 == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + long size1 = this.keyValues2.size(); + out.writeArrayStart(); + out.setItemCount(size1); + long actualSize1 = 0; + for (KeyValue2 e1: this.keyValues2) { + actualSize1++; + out.startItem(); + e1.customEncode(out); + } + out.writeArrayEnd(); + if (actualSize1 != size1) + throw new java.util.ConcurrentModificationException("Array-size written was " + size1 + ", but element count was " + actualSize1 + "."); + } + + if (this.keyValues3 == null) { + out.writeIndex(0); + out.writeNull(); + } else { + out.writeIndex(1); + long size2 = this.keyValues3.size(); + out.writeArrayStart(); + out.setItemCount(size2); + long actualSize2 = 0; + for (KeyValue3 e2: this.keyValues3) { + actualSize2++; + out.startItem(); + e2.customEncode(out); + } + out.writeArrayEnd(); + if (actualSize2 != size2) + throw new java.util.ConcurrentModificationException("Array-size written was " + size2 + ", but element count was " + actualSize2 + "."); + } + + this.address.customEncode(out); + + } + + @Override + public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.userId = in.readString(this.userId instanceof Utf8 ? (Utf8)this.userId : null); + + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + + if (in.readIndex() != 1) { + in.readNull(); + this.biography = null; + } else { + this.biography = in.readString(this.biography instanceof Utf8 ? (Utf8)this.biography : null); + } + + if (in.readIndex() != 1) { + in.readNull(); + this.eventTimestamp = null; + } else { + this.eventTimestamp = in.readLong(); + } + + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues = null; + } else { + long size0 = in.readArrayStart(); + java.util.List a0 = this.keyValues; + if (a0 == null) { + a0 = new SpecificData.Array((int)size0, SCHEMA$.getField("keyValues").schema().getTypes().get(1)); + this.keyValues = a0; + } else a0.clear(); + SpecificData.Array ga0 = (a0 instanceof SpecificData.Array ? (SpecificData.Array)a0 : null); + for ( ; 0 < size0; size0 = in.arrayNext()) { + for ( ; size0 != 0; size0--) { + KeyValue e0 = (ga0 != null ? ga0.peek() : null); + if (e0 == null) { + e0 = new KeyValue(); + } + e0.customDecode(in); + a0.add(e0); + } + } + } + + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues2 = null; + } else { + long size1 = in.readArrayStart(); + java.util.List a1 = this.keyValues2; + if (a1 == null) { + a1 = new SpecificData.Array((int)size1, SCHEMA$.getField("keyValues2").schema().getTypes().get(1)); + this.keyValues2 = a1; + } else a1.clear(); + SpecificData.Array ga1 = (a1 instanceof SpecificData.Array ? (SpecificData.Array)a1 : null); + for ( ; 0 < size1; size1 = in.arrayNext()) { + for ( ; size1 != 0; size1--) { + KeyValue2 e1 = (ga1 != null ? ga1.peek() : null); + if (e1 == null) { + e1 = new KeyValue2(); + } + e1.customDecode(in); + a1.add(e1); + } + } + } + + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues3 = null; + } else { + long size2 = in.readArrayStart(); + java.util.List a2 = this.keyValues3; + if (a2 == null) { + a2 = new SpecificData.Array((int)size2, SCHEMA$.getField("keyValues3").schema().getTypes().get(1)); + this.keyValues3 = a2; + } else a2.clear(); + SpecificData.Array ga2 = (a2 instanceof SpecificData.Array ? (SpecificData.Array)a2 : null); + for ( ; 0 < size2; size2 = in.arrayNext()) { + for ( ; size2 != 0; size2--) { + KeyValue3 e2 = (ga2 != null ? ga2.peek() : null); + if (e2 == null) { + e2 = new KeyValue3(); + } + e2.customDecode(in); + a2.add(e2); + } + } + } + + if (this.address == null) { + this.address = new AddressEntry(); + } + this.address.customDecode(in); + + } else { + for (int i = 0; i < 8; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.userId = in.readString(this.userId instanceof Utf8 ? (Utf8)this.userId : null); + break; + + case 1: + this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); + break; + + case 2: + if (in.readIndex() != 1) { + in.readNull(); + this.biography = null; + } else { + this.biography = in.readString(this.biography instanceof Utf8 ? (Utf8)this.biography : null); + } + break; + + case 3: + if (in.readIndex() != 1) { + in.readNull(); + this.eventTimestamp = null; + } else { + this.eventTimestamp = in.readLong(); + } + break; + + case 4: + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues = null; + } else { + long size0 = in.readArrayStart(); + java.util.List a0 = this.keyValues; + if (a0 == null) { + a0 = new SpecificData.Array((int)size0, SCHEMA$.getField("keyValues").schema().getTypes().get(1)); + this.keyValues = a0; + } else a0.clear(); + SpecificData.Array ga0 = (a0 instanceof SpecificData.Array ? (SpecificData.Array)a0 : null); + for ( ; 0 < size0; size0 = in.arrayNext()) { + for ( ; size0 != 0; size0--) { + KeyValue e0 = (ga0 != null ? ga0.peek() : null); + if (e0 == null) { + e0 = new KeyValue(); + } + e0.customDecode(in); + a0.add(e0); + } + } + } + break; + + case 5: + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues2 = null; + } else { + long size1 = in.readArrayStart(); + java.util.List a1 = this.keyValues2; + if (a1 == null) { + a1 = new SpecificData.Array((int)size1, SCHEMA$.getField("keyValues2").schema().getTypes().get(1)); + this.keyValues2 = a1; + } else a1.clear(); + SpecificData.Array ga1 = (a1 instanceof SpecificData.Array ? (SpecificData.Array)a1 : null); + for ( ; 0 < size1; size1 = in.arrayNext()) { + for ( ; size1 != 0; size1--) { + KeyValue2 e1 = (ga1 != null ? ga1.peek() : null); + if (e1 == null) { + e1 = new KeyValue2(); + } + e1.customDecode(in); + a1.add(e1); + } + } + } + break; + + case 6: + if (in.readIndex() != 1) { + in.readNull(); + this.keyValues3 = null; + } else { + long size2 = in.readArrayStart(); + java.util.List a2 = this.keyValues3; + if (a2 == null) { + a2 = new SpecificData.Array((int)size2, SCHEMA$.getField("KeyValues3").schema().getTypes().get(1)); + this.keyValues3 = a2; + } else a2.clear(); + SpecificData.Array ga2 = (a2 instanceof SpecificData.Array ? (SpecificData.Array)a2 : null); + for ( ; 0 < size2; size2 = in.arrayNext()) { + for ( ; size2 != 0; size2--) { + KeyValue3 e2 = (ga2 != null ? ga2.peek() : null); + if (e2 == null) { + e2 = new KeyValue3(); + } + e2.customDecode(in); + a2.add(e2); + } + } + } + break; + + case 7: + if (this.address == null) { + this.address = new AddressEntry(); + } + this.address.customDecode(in); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/serializers/avro/src/test/resources/avro/user.avsc b/serializers/avro/src/test/resources/avro/user.avsc new file mode 100644 index 000000000..d21cd1f31 --- /dev/null +++ b/serializers/avro/src/test/resources/avro/user.avsc @@ -0,0 +1,89 @@ +{ + "type": "record", + "namespace": "io.openmessaging.benchmark.driver.pravega.schema.generated.avro", + "name": "User", + "fields": [ + { + "name": "userId", + "type": "string" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "biography", + "type": ["null", "string"], + "default": null + }, + { + "name": "eventTimestamp", + "type": ["null", "long"], + "default": null + }, + { + "name": "keyValues", + "type": ["null", { + "type": "array", + "items": { + "name": "KeyValue", + "type": "record", + "fields": [ + {"name":"name", "type":"string"}, + {"name":"value", "type":"string"} + ] + } + }] + }, + { + "name": "keyValues2", + "type": ["null", { + "type": "array", + "items": { + "name": "KeyValue2", + "type": "record", + "fields": [ + {"name":"name", "type":"string"}, + {"name":"value", "type":"string"} + ] + } + }] + }, + { + "name": "keyValues3", + "type": ["null", { + "type": "array", + "items": { + "name": "KeyValue3", + "type": "record", + "fields": [ + {"name":"name", "type":"string"}, + {"name":"value", "type":"string"} + ] + } + }] + }, + { + "name": "address", + "type": { + "name" : "AddressEntry", + "type" : "record", + "fields": [ + { + "name": "streetAddress", + "type": "string" + }, + { + "name": "postalCode", + "type": ["null", "int"], + "default": null + }, + { + "name": "city", + "type": "string" + } + ] + } + } + ] +} \ No newline at end of file