You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dk...@apache.org on 2018/11/02 20:54:26 UTC
[avro] branch master updated: Squashed commit of the following:
This is an automated email from the ASF dual-hosted git repository.
dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new d799e18 Squashed commit of the following:
d799e18 is described below
commit d799e1829a39ca0379f3e12d2e8cfdf5fcd26151
Author: Daniel Kulp <dk...@apache.org>
AuthorDate: Fri Nov 2 16:40:09 2018 -0400
Squashed commit of the following:
commit 6d4d6d6a963fd2363d9f5549f76140bdddfceb7d
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Sun Oct 16 17:22:53 2016 +0200
AVRO-1605 - Removed some unnecessary Accessor methods and callers
commit adcefac6cc1c7021b2a27da16b40c1253eff64cc
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Thu Sep 29 18:35:26 2016 +0200
AVRO-1605 - Remove Jackson classes from public API (Removed jackson references from javadoc)
commit dc2ca7ee9f881901aaf23d9221cc2d6413b43dc4
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Thu Sep 29 14:31:40 2016 +0200
AVRO-1605 - Remove Jackson classes from public API
commit 4e4c5ec63b3b0cf203e3af21c1cbc7a51d63c9f4
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Wed Sep 28 17:08:15 2016 +0200
AVRO-1605 - Remove Jackson classes from public API (INCOMPLETE#4)
commit 5fb5a5c14fadc03f44879f029114c4705749dfad
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Wed Sep 28 16:54:44 2016 +0200
AVRO-1605 - Remove Jackson classes from public API (INCOMPLETE#3)
commit 378fcc5aa6be560c301e23b73f919bc0eb98dd05
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Wed Sep 28 11:11:40 2016 +0200
AVRO-1605 - Remove Jackson classes from public API (INCOMPLETE#2)
commit 12533657f9bc73c73b1009ed2d9dd39ca2401a20
Author: Gabor Szadovszky <ga...@cloudera.com>
Date: Mon Sep 26 16:25:19 2016 +0200
AVRO-1605 - Remove Jackson classes from public API (INCOMPLETE)
---
.../main/java/org/apache/avro/JsonProperties.java | 45 ++++----
.../src/main/java/org/apache/avro/Protocol.java | 21 ++++
.../avro/src/main/java/org/apache/avro/Schema.java | 63 ++++++++---
.../src/main/java/org/apache/avro/data/Json.java | 54 +---------
.../org/apache/avro/data/RecordBuilderBase.java | 2 +-
.../java/org/apache/avro/generic/GenericData.java | 7 +-
.../java/org/apache/avro/io/EncoderFactory.java | 4 +-
.../main/java/org/apache/avro/io/JsonEncoder.java | 4 +-
.../avro/io/parsing/ResolvingGrammarGenerator.java | 22 ++--
.../java/org/apache/avro/reflect/ReflectData.java | 9 +-
.../org/apache/avro/util/internal/Accessor.java | 119 +++++++++++++++++++++
.../java/org/apache/avro/reflect/TestReflect.java | 3 +-
.../avro/compiler/specific/SpecificCompiler.java | 53 +++++----
.../javacc/org/apache/avro/compiler/idl/idl.jj | 32 +++---
.../org/apache/avro/protobuf/ProtobufData.java | 3 +-
.../java/org/apache/avro/tool/RpcSendTool.java | 13 +--
.../java/org/apache/trevni/avro/RandomData.java | 2 +-
17 files changed, 294 insertions(+), 162 deletions(-)
diff --git a/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java b/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java
index 97493fc..3844073 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java
@@ -20,9 +20,12 @@ package org.apache.avro;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.io.IOException;
+import org.apache.avro.util.internal.Accessor;
+import org.apache.avro.util.internal.Accessor.JsonPropertiesAccessor;
import org.apache.avro.util.internal.JacksonUtils;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -110,6 +113,16 @@ import com.fasterxml.jackson.databind.node.TextNode;
* @see org.apache.avro.data.Json
*/
public abstract class JsonProperties {
+
+ static {
+ Accessor.setAccessor(new JsonPropertiesAccessor() {
+ @Override
+ protected void addProp(JsonProperties props, String name, JsonNode value) {
+ props.addProp(name, value);
+ }
+ });
+ }
+
public static class Null {
private Null() {}
}
@@ -136,10 +149,8 @@ public abstract class JsonProperties {
/**
* Returns the value of the named property in this schema.
* Returns <tt>null</tt> if there is no property with that name.
- * @deprecated use {@link #getObjectProp(String)}
*/
- @Deprecated
- public synchronized JsonNode getJsonProp(String name) {
+ synchronized JsonNode getJsonProp(String name) {
return props.get(name);
}
@@ -164,18 +175,7 @@ public abstract class JsonProperties {
addProp(name, TextNode.valueOf(value));
}
- /**
- * Adds a property with the given name <tt>name</tt> and
- * value <tt>value</tt>. Neither <tt>name</tt> nor <tt>value</tt> can be
- * <tt>null</tt>. It is illegal to add a property if another with
- * the same name but different value already exists in this schema.
- *
- * @param name The name of the property to add
- * @param value The value for the property to add
- * @deprecated use {@link #addProp(String, Object)}
- */
- @Deprecated
- public synchronized void addProp(String name, JsonNode value) {
+ synchronized void addProp(String name, JsonNode value) {
if (reserved.contains(name))
throw new AvroRuntimeException("Can't set reserved property: " + name);
@@ -193,6 +193,16 @@ public abstract class JsonProperties {
addProp(name, JacksonUtils.toJsonNode(value));
}
+ /**
+ * Adds all the props from the specified json properties.
+ *
+ * @see #getObjectProps()
+ */
+ public void addAllProps(JsonProperties properties) {
+ for (Entry<String, JsonNode> entry : properties.getJsonProps().entrySet())
+ addProp(entry.getKey(), entry.getValue());
+ }
+
/** Return the defined properties that have string values. */
@Deprecated public Map<String,String> getProps() {
Map<String,String> result = new LinkedHashMap<>();
@@ -211,11 +221,10 @@ public abstract class JsonProperties {
}
/**
- * Return the defined properties as an unmodifiable Map.
+ * Return the defined properties as an unmodifieable Map.
* @deprecated use {@link #getObjectProps()}
*/
- @Deprecated
- public Map<String,JsonNode> getJsonProps() {
+ Map<String,JsonNode> getJsonProps() {
return Collections.unmodifiableMap(props);
}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/Protocol.java b/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
index f4a184e..c5800a7 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Protocol.java
@@ -231,6 +231,15 @@ public class Protocol extends JsonProperties {
super(PROTOCOL_RESERVED);
}
+ /**
+ * Constructs a similar Protocol instance with the same {@code name}, {@code doc}, and {@code namespace} as {code p}
+ * has. It also copies all the {@code props}.
+ */
+ public Protocol(Protocol p) {
+ this(p.getName(), p.getDoc(), p.getNamespace());
+ props.putAll(p.props);
+ }
+
public Protocol(String name, String doc, String namespace) {
super(PROTOCOL_RESERVED);
this.name = name;
@@ -271,6 +280,12 @@ public class Protocol extends JsonProperties {
public Message createMessage(String name, String doc, Schema request) {
return createMessage(name, doc, new LinkedHashMap<String,String>(),request);
}
+
+ /** Create a one-way message using the {@code name}, {@code doc}, and {@code props} of {@code m}. */
+ public Message createMessage(Message m, Schema request) {
+ return createMessage(m.getName(), m.getDoc(), m.getJsonProps(), request);
+ }
+
/** Create a one-way message. */
public <T> Message createMessage(String name, String doc,
Map<String,T> propMap, Schema request) {
@@ -284,6 +299,12 @@ public class Protocol extends JsonProperties {
return createMessage(name, doc, new LinkedHashMap<String,String>(),
request, response, errors);
}
+
+ /** Create a two-way message using the {@code name}, {@code doc}, and {@code props} of {@code m}. */
+ public Message createMessage(Message m, Schema request, Schema response, Schema errors) {
+ return createMessage(m.getName(), m.getDoc(), m.getJsonProps(), request, response, errors);
+ }
+
/** Create a two-way message. */
public <T> Message createMessage(String name, String doc,
Map<String,T> propMap, Schema request,
diff --git a/lang/java/avro/src/main/java/org/apache/avro/Schema.java b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
index 280492c..6c63ddc 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Schema.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
@@ -36,6 +36,8 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import org.apache.avro.util.internal.Accessor;
+import org.apache.avro.util.internal.Accessor.FieldAccessor;
import org.apache.avro.util.internal.JacksonUtils;
import com.fasterxml.jackson.core.JsonFactory;
@@ -136,7 +138,7 @@ public abstract class Schema extends JsonProperties {
int hashCode = NO_HASHCODE;
- @Override public void addProp(String name, JsonNode value) {
+ @Override void addProp(String name, JsonNode value) {
super.addProp(name, value);
hashCode = NO_HASHCODE;
}
@@ -392,6 +394,25 @@ public abstract class Schema extends JsonProperties {
/** A field within a record. */
public static class Field extends JsonProperties {
+ static {
+ Accessor.setAccessor(new FieldAccessor() {
+ @Override
+ protected JsonNode defaultValue(Field field) {
+ return field.defaultValue();
+ }
+
+ @Override
+ protected Field createField(String name, Schema schema, String doc, JsonNode defaultValue) {
+ return new Field(name, schema, doc, defaultValue);
+ }
+
+ @Override
+ protected Field createField(String name, Schema schema, String doc, JsonNode defaultValue, boolean validate, Order order) {
+ return new Field(name, schema, doc, defaultValue, validate, order);
+ }
+ });
+ }
+
/** How values of this field should be ordered when sorting records. */
public enum Order {
ASCENDING, DESCENDING, IGNORE;
@@ -407,12 +428,11 @@ public abstract class Schema extends JsonProperties {
private final Order order;
private Set<String> aliases;
- /** @deprecated use {@link #Field(String, Schema, String, Object)} */
- @Deprecated
- public Field(String name, Schema schema, String doc,
+ Field(String name, Schema schema, String doc,
JsonNode defaultValue) {
this(name, schema, doc, defaultValue, Order.ASCENDING);
}
+
/** @deprecated use {@link #Field(String, Schema, String, Object, Order)} */
@Deprecated
public Field(String name, Schema schema, String doc,
@@ -430,6 +450,18 @@ public abstract class Schema extends JsonProperties {
: defaultValue;
this.order = order;
}
+
+ /**
+ * Constructs a new Field instance with the same {@code name}, {@code doc}, {@code defaultValue}, and {@code order}
+ * as {@code field} has with changing the schema to the specified one. It also copies all the {@code props} and
+ * {@code aliases}.
+ */
+ public Field(Field field, Schema schema) {
+ this(field.name, schema, field.doc, field.defaultValue, field.order);
+ props.putAll(field.props);
+ if (field.aliases != null)
+ aliases = new LinkedHashSet<String>(field.aliases);
+ }
/**
* @param defaultValue the default value for this field specified using the mapping
* in {@link JsonProperties}
@@ -453,8 +485,7 @@ public abstract class Schema extends JsonProperties {
public Schema schema() { return schema; }
/** Field's documentation within the record, if set. May return null. */
public String doc() { return doc; }
- /** @deprecated use {@link #defaultVal() } */
- @Deprecated public JsonNode defaultValue() { return defaultValue; }
+ JsonNode defaultValue() { return defaultValue; }
/**
* @return the default value for this field specified using the mapping
* in {@link JsonProperties}
@@ -1080,8 +1111,7 @@ public abstract class Schema extends JsonProperties {
* The contents of <tt>file</tt> is expected to be in UTF-8 format.
* @param file The file to read the schema from.
* @return The freshly built Schema.
- * @throws IOException if there was trouble reading the contents
- * @throws JsonParseException if the contents are invalid
+ * @throws IOException if there was trouble reading the contents or they are invalid
* @deprecated use {@link Schema.Parser} instead.
*/
public static Schema parse(File file) throws IOException {
@@ -1093,8 +1123,7 @@ public abstract class Schema extends JsonProperties {
* The contents of <tt>in</tt> is expected to be in UTF-8 format.
* @param in The input stream to read the schema from.
* @return The freshly built Schema.
- * @throws IOException if there was trouble reading the contents
- * @throws JsonParseException if the contents are invalid
+ * @throws IOException if there was trouble reading the contents or they are invalid
* @deprecated use {@link Schema.Parser} instead.
*/
public static Schema parse(InputStream in) throws IOException {
@@ -1428,12 +1457,7 @@ public abstract class Schema extends JsonProperties {
return jsonNode != null ? jsonNode.textValue() : null;
}
- /**
- * Parses a string as Json.
- * @deprecated use {@link org.apache.avro.data.Json#parseJson(String)}
- */
- @Deprecated
- public static JsonNode parseJson(String s) {
+ static JsonNode parseJson(String s) {
try {
return MAPPER.readTree(FACTORY.createJsonParser(new StringReader(s)));
} catch (JsonParseException e) {
@@ -1443,6 +1467,13 @@ public abstract class Schema extends JsonProperties {
}
}
+ /**
+ * Parses the specified json string to an object.
+ */
+ public static Object parseJsonToObject(String s) {
+ return JacksonUtils.toObject(parseJson(s));
+ }
+
/** Rewrite a writer's schema using the aliases from a reader's schema. This
* permits reading records, enums and fixed schemas whose names have changed,
* and records whose field names have changed. The returned schema always
diff --git a/lang/java/avro/src/main/java/org/apache/avro/data/Json.java b/lang/java/avro/src/main/java/org/apache/avro/data/Json.java
index c4f75e6..09c2363 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/data/Json.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/data/Json.java
@@ -67,52 +67,6 @@ public class Json {
}
}
- /**
- * {@link DatumWriter} for arbitrary Json data.
- * @deprecated use {@link ObjectWriter}
- */
- @Deprecated
- public static class Writer implements DatumWriter<JsonNode> {
-
- @Override public void setSchema(Schema schema) {
- if (!SCHEMA.equals(schema))
- throw new RuntimeException("Not the Json schema: "+schema);
- }
-
- @Override
- public void write(JsonNode datum, Encoder out) throws IOException {
- Json.write(datum, out);
- }
- }
-
- /**
- * {@link DatumReader} for arbitrary Json data.
- * @deprecated use {@link ObjectReader}
- */
- @Deprecated
- public static class Reader implements DatumReader<JsonNode> {
- private Schema written;
- private ResolvingDecoder resolver;
-
- @Override public void setSchema(Schema schema) {
- this.written = SCHEMA.equals(written) ? null : schema;
- }
-
- @Override
- public JsonNode read(JsonNode reuse, Decoder in) throws IOException {
- if (written == null) // same schema
- return Json.read(in);
-
- // use a resolver to adapt alternate version of Json schema
- if (resolver == null)
- resolver = DecoderFactory.get().resolvingDecoder(written, SCHEMA, null);
- resolver.configure(in);
- JsonNode result = Json.read(resolver);
- resolver.drain();
- return result;
- }
- }
-
/** {@link DatumWriter} for arbitrary Json data using the object model described
* in {@link org.apache.avro.JsonProperties}. */
public static class ObjectWriter implements DatumWriter<Object> {
@@ -181,10 +135,8 @@ public class Json {
/**
* Write Json data as Avro data.
- * @deprecated internal method
*/
- @Deprecated
- public static void write(JsonNode node, Encoder out) throws IOException {
+ private static void write(JsonNode node, Encoder out) throws IOException {
switch(node.asToken()) {
case VALUE_NUMBER_INT:
out.writeIndex(JsonType.LONG.ordinal());
@@ -240,10 +192,8 @@ public class Json {
/**
* Read Json data from Avro data.
- * @deprecated internal method
*/
- @Deprecated
- public static JsonNode read(Decoder in) throws IOException {
+ private static JsonNode read(Decoder in) throws IOException {
switch (JsonType.values()[in.readIndex()]) {
case LONG:
return new LongNode(in.readLong());
diff --git a/lang/java/avro/src/main/java/org/apache/avro/data/RecordBuilderBase.java b/lang/java/avro/src/main/java/org/apache/avro/data/RecordBuilderBase.java
index 8805ba5..106c500 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/data/RecordBuilderBase.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/data/RecordBuilderBase.java
@@ -85,7 +85,7 @@ public abstract class RecordBuilderBase<T extends IndexedRecord>
if (isValidValue(field, value)) {
return;
}
- else if (field.defaultValue() != null) {
+ else if (field.defaultVal() != null) {
return;
}
else {
diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
index 835d3a0..419cdba 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
@@ -49,10 +49,11 @@ import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
-import org.apache.avro.io.parsing.ResolvingGrammarGenerator;
import org.apache.avro.util.Utf8;
+import org.apache.avro.util.internal.Accessor;
import com.fasterxml.jackson.databind.JsonNode;
+
import com.google.common.collect.MapMaker;
/** Utilities for generic Java data. See {@link GenericRecordBuilder} for a convenient
@@ -993,7 +994,7 @@ public class GenericData {
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Object getDefaultValue(Field field) {
- JsonNode json = field.defaultValue();
+ JsonNode json = Accessor.defaultValue(field);
if (json == null)
throw new AvroMissingFieldException("Field " + field
+ " not set and has no default value", field);
@@ -1013,7 +1014,7 @@ public class GenericData {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null);
- ResolvingGrammarGenerator.encode(encoder, field.schema(), json);
+ Accessor.encode(encoder, field.schema(), json);
encoder.flush();
BinaryDecoder decoder =
DecoderFactory.get().binaryDecoder(baos.toByteArray(), null);
diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java b/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java
index 52c52a6..192536c 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java
@@ -320,10 +320,8 @@ public class EncoderFactory {
* The JsonGenerator to write with. Cannot be null.
* @return A JsonEncoder configured with <i>gen</i> and <i>schema</i>
* @throws IOException
- * @deprecated internal method
*/
- @Deprecated
- public JsonEncoder jsonEncoder(Schema schema, JsonGenerator gen)
+ JsonEncoder jsonEncoder(Schema schema, JsonGenerator gen)
throws IOException {
return new JsonEncoder(schema, gen);
}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java b/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java
index 3328d9f..44657f0 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java
@@ -131,10 +131,8 @@ public class JsonEncoder extends ParsingEncoder implements Parser.ActionHandler
* The JsonGenerator to direct output to. Cannot be null.
* @throws IOException
* @return this JsonEncoder
- * @deprecated internal method
*/
- @Deprecated
- public JsonEncoder configure(JsonGenerator generator) throws IOException {
+ private JsonEncoder configure(JsonGenerator generator) throws IOException {
if (null == generator)
throw new NullPointerException("JsonGenerator cannot be null");
if (null != parser) {
diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java b/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java
index 47e12a9..7197882 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java
@@ -30,6 +30,8 @@ import org.apache.avro.Schema;
import org.apache.avro.Schema.Field;
import org.apache.avro.io.Encoder;
import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.util.internal.Accessor;
+import org.apache.avro.util.internal.Accessor.ResolvingGrammarGeneratorAccessor;
import com.fasterxml.jackson.databind.JsonNode;
@@ -38,6 +40,16 @@ import com.fasterxml.jackson.databind.JsonNode;
* schemas.
*/
public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
+
+ static {
+ Accessor.setAccessor(new ResolvingGrammarGeneratorAccessor() {
+ @Override
+ protected void encode(Encoder e, Schema s, JsonNode n) throws IOException {
+ ResolvingGrammarGenerator.encode(e, s, n);
+ }
+ });
+ }
+
/**
* Resolves the writer schema <tt>writer</tt> and the reader schema
* <tt>reader</tt> and returns the start symbol for the grammar generated.
@@ -235,7 +247,7 @@ public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
for (Field rf : rfields) {
String fname = rf.name();
if (writer.getField(fname) == null) {
- if (rf.defaultValue() == null) {
+ if (rf.defaultVal() == null) {
result = Symbol.error("Found " + writer.getFullName()
+ ", expecting " + reader.getFullName()
+ ", missing required field " + fname);
@@ -283,7 +295,7 @@ public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
String fname = rf.name();
Field wf = writer.getField(fname);
if (wf == null) {
- byte[] bb = getBinary(rf.schema(), rf.defaultValue());
+ byte[] bb = getBinary(rf.schema(), Accessor.defaultValue(rf));
production[--count] = Symbol.defaultStartAction(bb);
production[--count] = generate(rf.schema(), rf.schema(), seen);
production[--count] = Symbol.DEFAULT_END_ACTION;
@@ -317,10 +329,8 @@ public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
* @param s The schema for the object being encoded.
* @param n The Json node to encode.
* @throws IOException
- * @deprecated internal method
*/
- @Deprecated
- public static void encode(Encoder e, Schema s, JsonNode n)
+ static void encode(Encoder e, Schema s, JsonNode n)
throws IOException {
switch (s.getType()) {
case RECORD:
@@ -328,7 +338,7 @@ public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
String name = f.name();
JsonNode v = n.get(name);
if (v == null) {
- v = f.defaultValue();
+ v = Accessor.defaultValue(f);
}
if (v == null) {
throw new AvroTypeException("No default value for: " + name);
diff --git a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
index 6c59a69..d8eb2cb 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
@@ -38,13 +38,12 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.NullNode;
import com.google.common.collect.MapMaker;
import org.apache.avro.AvroRemoteException;
import org.apache.avro.AvroRuntimeException;
import org.apache.avro.AvroTypeException;
import org.apache.avro.Conversion;
+import org.apache.avro.JsonProperties;
import org.apache.avro.LogicalType;
import org.apache.avro.Protocol;
import org.apache.avro.Protocol.Message;
@@ -611,15 +610,15 @@ public class ReflectData extends SpecificData {
Schema fieldSchema = createFieldSchema(field, names);
AvroDefault defaultAnnotation
= field.getAnnotation(AvroDefault.class);
- JsonNode defaultValue = (defaultAnnotation == null)
+ Object defaultValue = (defaultAnnotation == null)
? null
- : Schema.parseJson(defaultAnnotation.value());
+ : Schema.parseJsonToObject(defaultAnnotation.value());
if (defaultValue == null
&& fieldSchema.getType() == Schema.Type.UNION) {
Schema defaultType = fieldSchema.getTypes().get(0);
if (defaultType.getType() == Schema.Type.NULL) {
- defaultValue = NullNode.getInstance();
+ defaultValue = JsonProperties.NULL_VALUE;
}
}
AvroName annotatedName = field.getAnnotation(AvroName.class); // Rename fields
diff --git a/lang/java/avro/src/main/java/org/apache/avro/util/internal/Accessor.java b/lang/java/avro/src/main/java/org/apache/avro/util/internal/Accessor.java
new file mode 100644
index 0000000..7b39ba7
--- /dev/null
+++ b/lang/java/avro/src/main/java/org/apache/avro/util/internal/Accessor.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.avro.util.internal;
+
+import java.io.IOException;
+
+import org.apache.avro.JsonProperties;
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Field;
+import org.apache.avro.Schema.Field.Order;
+import org.apache.avro.io.Encoder;
+import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.io.JsonEncoder;
+import org.apache.avro.io.parsing.ResolvingGrammarGenerator;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class Accessor {
+ public abstract static class JsonPropertiesAccessor {
+ protected abstract void addProp(JsonProperties props, String name, JsonNode value);
+ }
+
+ public abstract static class FieldAccessor {
+ protected abstract JsonNode defaultValue(Field field);
+
+ protected abstract Field createField(String name, Schema schema, String doc, JsonNode defaultValue, boolean validate, Order order);
+
+ protected abstract Field createField(String name, Schema schema, String doc, JsonNode defaultValue);
+ }
+
+ public abstract static class ResolvingGrammarGeneratorAccessor {
+ protected abstract void encode(Encoder e, Schema s, JsonNode n) throws IOException;
+ }
+
+ public abstract static class EncoderFactoryAccessor {
+ protected abstract JsonEncoder jsonEncoder(EncoderFactory factory, Schema schema, JsonGenerator gen)
+ throws IOException;
+ }
+
+ private static volatile JsonPropertiesAccessor jsonPropertiesAccessor;
+
+ private static volatile FieldAccessor fieldAccessor;
+
+ private static volatile ResolvingGrammarGeneratorAccessor resolvingGrammarGeneratorAccessor;
+
+ public static void setAccessor(JsonPropertiesAccessor accessor) {
+ if (jsonPropertiesAccessor != null)
+ throw new IllegalStateException("JsonPropertiesAccessor already initialized");
+ jsonPropertiesAccessor = accessor;
+ }
+
+ public static void setAccessor(FieldAccessor accessor) {
+ if (fieldAccessor != null)
+ throw new IllegalStateException("FieldAccessor already initialized");
+ fieldAccessor = accessor;
+ }
+
+ private static FieldAccessor fieldAccessor() {
+ if (fieldAccessor == null)
+ ensureLoaded(Field.class);
+ return fieldAccessor;
+ }
+
+ public static void setAccessor(ResolvingGrammarGeneratorAccessor accessor) {
+ if (resolvingGrammarGeneratorAccessor != null)
+ throw new IllegalStateException("ResolvingGrammarGeneratorAccessor already initialized");
+ resolvingGrammarGeneratorAccessor = accessor;
+ }
+
+ private static ResolvingGrammarGeneratorAccessor resolvingGrammarGeneratorAccessor() {
+ if (resolvingGrammarGeneratorAccessor == null)
+ ensureLoaded(ResolvingGrammarGenerator.class);
+ return resolvingGrammarGeneratorAccessor;
+ }
+
+ private static void ensureLoaded(Class<?> c) {
+ try {
+ Class.forName(c.getName());
+ } catch (ClassNotFoundException e) {
+ // Shall never happen as the class is specified by its Class instance
+ }
+ }
+
+ public static void addProp(JsonProperties props, String name, JsonNode value) {
+ jsonPropertiesAccessor.addProp(props, name, value);
+ }
+
+ public static JsonNode defaultValue(Field field) {
+ return fieldAccessor.defaultValue(field);
+ }
+
+ public static void encode(Encoder e, Schema s, JsonNode n) throws IOException {
+ resolvingGrammarGeneratorAccessor().encode(e, s, n);
+ }
+
+ public static Field createField(String name, Schema schema, String doc, JsonNode defaultValue, boolean validate, Order order) {
+ return fieldAccessor().createField(name, schema, doc, defaultValue, validate, order);
+ }
+
+ public static Field createField(String name, Schema schema, String doc, JsonNode defaultValue) {
+ return fieldAccessor().createField(name, schema, doc, defaultValue);
+ }
+
+}
diff --git a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
index cb572f0..85debac 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
@@ -37,6 +37,7 @@ import java.util.Random;
import org.apache.avro.AvroRuntimeException;
import org.apache.avro.AvroTypeException;
+import org.apache.avro.JsonProperties;
import org.apache.avro.Protocol;
import org.apache.avro.Schema;
import org.apache.avro.SchemaBuilder;
@@ -389,7 +390,7 @@ public class TestReflect {
Schema r11Record = ReflectData.get().getSchema(R11.class);
assertEquals(Schema.Type.RECORD, r11Record.getType());
Field r11Field = r11Record.getField("text");
- assertEquals(NullNode.getInstance(), r11Field.defaultValue());
+ assertEquals(JsonProperties.NULL_VALUE, r11Field.defaultVal());
Schema r11FieldSchema = r11Field.schema();
assertEquals(Schema.Type.UNION, r11FieldSchema.getType());
assertEquals(Schema.Type.NULL, r11FieldSchema.getTypes().get(0).getType());
diff --git a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
index 5470037..aa7c5c3 100644
--- a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
+++ b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
@@ -40,7 +40,6 @@ import org.apache.avro.LogicalTypes;
import org.apache.avro.data.Jsr310TimeConversions;
import org.apache.avro.data.TimeConversions;
import org.apache.avro.specific.SpecificData;
-import com.fasterxml.jackson.databind.JsonNode;
import org.apache.avro.Protocol;
import org.apache.avro.Protocol.Message;
@@ -545,9 +544,9 @@ public class SpecificCompiler {
Protocol newP = new Protocol(p.getName(), p.getDoc(), p.getNamespace());
Map<Schema,Schema> types = new LinkedHashMap<>();
- // Copy properties
- for (Map.Entry<String,JsonNode> prop : p.getJsonProps().entrySet())
- newP.addProp(prop.getKey(), prop.getValue()); // copy props
+ for (Map.Entry<String, Object> a : p.getObjectProps().entrySet()) {
+ newP.addProp(a.getKey(), a.getValue());
+ }
// annotate types
Collection<Schema> namedTypes = new LinkedHashSet<>();
@@ -559,9 +558,9 @@ public class SpecificCompiler {
Map<String,Message> newM = newP.getMessages();
for (Message m : p.getMessages().values())
newM.put(m.getName(), m.isOneWay()
- ? newP.createMessage(m.getName(), m.getDoc(), m.getJsonProps(),
+ ? newP.createMessage(m,
addStringType(m.getRequest(), types))
- : newP.createMessage(m.getName(), m.getDoc(), m.getJsonProps(),
+ : newP.createMessage(m,
addStringType(m.getRequest(), types),
addStringType(m.getResponse(), types),
addStringType(m.getErrors(), types)));
@@ -592,12 +591,7 @@ public class SpecificCompiler {
List<Field> newFields = new ArrayList<>();
for (Field f : s.getFields()) {
Schema fSchema = addStringType(f.schema(), seen);
- Field newF =
- new Field(f.name(), fSchema, f.doc(), f.defaultValue(), f.order());
- for (Map.Entry<String,JsonNode> p : f.getJsonProps().entrySet())
- newF.addProp(p.getKey(), p.getValue()); // copy props
- for (String a : f.aliases())
- newF.addAlias(a); // copy aliases
+ Field newF = new Field(f, fSchema);
newFields.add(newF);
}
result.setFields(newFields);
@@ -618,8 +612,7 @@ public class SpecificCompiler {
result = Schema.createUnion(types);
break;
}
- for (Map.Entry<String,JsonNode> p : s.getJsonProps().entrySet())
- result.addProp(p.getKey(), p.getValue()); // copy props
+ result.addAllProps(s);
seen.put(s, result);
return result;
}
@@ -640,14 +633,17 @@ public class SpecificCompiler {
default:
throw new IllegalArgumentException("Can't check string-type of non-string/map type: " + s);
}
- JsonNode override = s.getJsonProp(prop);
- if (override != null) return override.textValue();
+ return getStringType(s.getObjectProp(prop));
+ }
+ private String getStringType(Object overrideClassProperty) {
+ if (overrideClassProperty != null)
+ return overrideClassProperty.toString();
switch (stringType) {
case String: return "java.lang.String";
case Utf8: return "org.apache.avro.util.Utf8";
case CharSequence: return "java.lang.CharSequence";
default: throw new RuntimeException("Unknown string type: "+stringType);
- }
+ }
}
/** Utility for template use. Returns true iff a STRING-schema or
@@ -685,14 +681,15 @@ public class SpecificCompiler {
return "java.util.List<" + javaType(schema.getElementType()) + ">";
case MAP:
return "java.util.Map<"
- + getStringType(schema)+ "," + javaType(schema.getValueType()) + ">";
+ + getStringType(schema.getObjectProp(SpecificData.KEY_CLASS_PROP))+","
+ + javaType(schema.getValueType()) + ">";
case UNION:
List<Schema> types = schema.getTypes(); // elide unions with null
if ((types.size() == 2) && types.contains(NULL_SCHEMA))
return javaType(types.get(types.get(0).equals(NULL_SCHEMA) ? 1 : 0));
return "java.lang.Object";
case STRING:
- return getStringType(schema);
+ return getStringType(schema.getObjectProp(SpecificData.CLASS_PROP));
case BYTES: return "java.nio.ByteBuffer";
case INT: return "java.lang.Integer";
case LONG: return "java.lang.Long";
@@ -814,17 +811,17 @@ public class SpecificCompiler {
/** Utility for template use. Returns the java annotations for a schema. */
public String[] javaAnnotations(JsonProperties props) {
- JsonNode value = props.getJsonProp("javaAnnotation");
+ Object value = props.getObjectProp("javaAnnotation");
if (value == null)
return new String[0];
- if (value.isTextual())
- return new String[] { value.textValue() };
- if (value.isArray()) {
- int i = 0;
- String[] result = new String[value.size()];
- for (JsonNode v : value)
- result[i++] = v.textValue();
- return result;
+ if (value instanceof String)
+ return new String[] { value.toString() };
+ if (value instanceof List) {
+ List<?> list = (List<?>) value;
+ List<String> annots = new ArrayList<String>();
+ for (Object o : list)
+ annots.add(o.toString());
+ return annots.toArray(new String[annots.size()]);
}
return new String[0];
}
diff --git a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
index 69fd8c5..258dd47 100644
--- a/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
+++ b/lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj
@@ -73,6 +73,7 @@ import org.apache.avro.LogicalTypes;
import org.apache.avro.Schema.*;
import org.apache.avro.Protocol;
import org.apache.avro.Protocol.*;
+import org.apache.avro.util.internal.Accessor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.*;
@@ -1010,7 +1011,7 @@ Protocol CompilationUnit():
/*
* Declaration syntax follows.
*/
-Schema NamedSchemaDeclaration(Map<String, JsonNode> props):
+private Schema NamedSchemaDeclaration(Map<String, JsonNode> props):
{
Schema s;
String savedSpace = this.namespace;
@@ -1034,7 +1035,7 @@ Schema NamedSchemaDeclaration(Map<String, JsonNode> props):
for (String alias : getTextProps("aliases", props, token))
s.addAlias(alias);
} else { // add all other props
- s.addProp(key, props.get(key));
+ Accessor.addProp(s, key, props.get(key));
}
return s;
@@ -1085,7 +1086,7 @@ Protocol ProtocolDeclaration():
for (String key : props.keySet())
if ("namespace".equals(key)) { // already handled: ignore
} else { // add all other props
- p.addProp(key, props.get(key));
+ Accessor.addProp(p, key, props.get(key));
}
}
ProtocolBody(p)
@@ -1275,7 +1276,7 @@ Schema RecordDeclaration():
}
}
-void SchemaProperty(Map<String, JsonNode> properties):
+private void SchemaProperty(Map<String, JsonNode> properties):
{
String key;
JsonNode val;
@@ -1305,7 +1306,7 @@ void FieldDeclaration(List<Field> fields):
";"
{
for (String key : props.keySet())
- type.addProp(key, props.get(key));
+ Accessor.addProp(type, key, props.get(key));
}
}
@@ -1327,15 +1328,16 @@ void VariableDeclarator(Schema type, List<Field> fields):
for (String key : props.keySet())
if ("order".equals(key))
order = Field.Order.valueOf(getTextProp(key,props,token).toUpperCase());
+
boolean validate = !SchemaResolver.isUnresolvedSchema(type);
- Field field = new Field(name,type, getDoc(), defaultValue, validate, order);
+ Field field = Accessor.createField(name, type, getDoc(), defaultValue, validate, order);
for (String key : props.keySet())
if ("order".equals(key)) { // already handled: ignore
} else if ("aliases".equals(key)) { // aliases
for (String alias : getTextProps("aliases", props, token))
field.addAlias(alias);
} else { // add all other props
- field.addProp(key, props.get(key));
+ Accessor.addProp(field, key, props.get(key));
}
fields.add(field);
}
@@ -1351,7 +1353,7 @@ String MessageDocumentation():
}
}
-Message MessageDeclaration(Protocol p, Map<String, JsonNode> props):
+private Message MessageDeclaration(Protocol p, Map<String, JsonNode> props):
{
String msgDoc;
String name;
@@ -1427,7 +1429,7 @@ Schema Type():
)
{
for (String key : props.keySet())
- s.addProp(key, props.get(key));
+ Accessor.addProp(s, key, props.get(key));
return s;
}
}
@@ -1585,7 +1587,7 @@ Token AnyIdentifier():
}
}
-JsonNode Json() :
+private JsonNode Json() :
{ String s; Token t; JsonNode n; }
{
( s = JsonString() { n = new TextNode(s); }
@@ -1610,7 +1612,7 @@ String JsonString() :
}
}
-JsonNode JsonObject() :
+private JsonNode JsonObject() :
{
ObjectNode o = FACTORY.objectNode();
}
@@ -1619,13 +1621,13 @@ JsonNode JsonObject() :
{ return o; }
}
-void JsonFields(ObjectNode o) :
+private void JsonFields(ObjectNode o) :
{}
{
JsonPair(o) [ "," JsonFields(o) ]
}
-void JsonPair(ObjectNode o) :
+private void JsonPair(ObjectNode o) :
{
String name;
JsonNode value;
@@ -1635,14 +1637,14 @@ void JsonPair(ObjectNode o) :
{ o.put(name, value); }
}
-JsonNode JsonArray() :
+private JsonNode JsonArray() :
{ ArrayNode a = FACTORY.arrayNode(); }
{
<LBRACK> [ JsonElements(a) ] <RBRACK>
{ return a; }
}
-void JsonElements(ArrayNode a) :
+private void JsonElements(ArrayNode a) :
{ JsonNode element; }
{
element=Json() { a.add(element); } [ "," JsonElements(a) ]
diff --git a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
index 7f9ae4e..c725ca0 100644
--- a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
+++ b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
@@ -46,6 +46,7 @@ import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.DescriptorProtos.FileOptions;
import org.apache.avro.util.ClassUtils;
+import org.apache.avro.util.internal.Accessor;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -213,7 +214,7 @@ public class ProtobufData extends GenericData {
List<Field> fields = new ArrayList<>();
for (FieldDescriptor f : descriptor.getFields())
- fields.add(new Field(f.getName(), getSchema(f), null, getDefault(f)));
+ fields.add(Accessor.createField(f.getName(), getSchema(f), null, getDefault(f)));
result.setFields(fields);
return result;
diff --git a/lang/java/tools/src/main/java/org/apache/avro/tool/RpcSendTool.java b/lang/java/tools/src/main/java/org/apache/avro/tool/RpcSendTool.java
index 8582a91..5db620b 100644
--- a/lang/java/tools/src/main/java/org/apache/avro/tool/RpcSendTool.java
+++ b/lang/java/tools/src/main/java/org/apache/avro/tool/RpcSendTool.java
@@ -34,13 +34,10 @@ import org.apache.avro.Protocol.Message;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.io.JsonEncoder;
import org.apache.avro.ipc.Ipc;
import org.apache.avro.ipc.generic.GenericRequestor;
-import com.fasterxml.jackson.core.JsonEncoding;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
-
/**
* Sends a single RPC message.
*/
@@ -106,11 +103,9 @@ public class RpcSendTool implements Tool {
private void dumpJson(PrintStream out, Schema schema, Object datum)
throws IOException {
DatumWriter<Object> writer = new GenericDatumWriter<>(schema);
- JsonGenerator g =
- new JsonFactory().createJsonGenerator(out, JsonEncoding.UTF8);
- g.useDefaultPrettyPrinter();
- writer.write(datum, EncoderFactory.get().jsonEncoder(schema, g));
- g.flush();
+ JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(schema, out, true);
+ writer.write(datum, jsonEncoder);
+ jsonEncoder.flush();
out.println();
out.flush();
}
diff --git a/lang/java/trevni/avro/src/test/java/org/apache/trevni/avro/RandomData.java b/lang/java/trevni/avro/src/test/java/org/apache/trevni/avro/RandomData.java
index 227549a..2426d89 100644
--- a/lang/java/trevni/avro/src/test/java/org/apache/trevni/avro/RandomData.java
+++ b/lang/java/trevni/avro/src/test/java/org/apache/trevni/avro/RandomData.java
@@ -64,7 +64,7 @@ public class RandomData implements Iterable<Object> {
case RECORD:
GenericRecord record = new GenericData.Record(schema);
for (Schema.Field field : schema.getFields()) {
- Object value = (field.getJsonProp(USE_DEFAULT) == null)
+ Object value = (field.getObjectProp(USE_DEFAULT) == null)
? generate(field.schema(), random, d+1)
: GenericData.get().getDefaultValue(field);
record.put(field.name(), value);