/** * Produces an opaque resolver that can be used to construct a new * {@link ResolvingDecoder#ResolvingDecoder(Object, Decoder)}. The * returned Object is immutable and hence can be simultaneously used * in many ResolvingDecoders. This method is reasonably expensive, the * users are encouraged to cache the result. * * @param writer The writer's schema. Cannot be null. * @param reader The reader's schema. Cannot be null. * @return The opaque resolver. * @throws IOException */ public static Object resolve(Schema writer, Schema reader) throws IOException { if (null == writer) { throw new NullPointerException("writer cannot be null!"); } if (null == reader) { throw new NullPointerException("reader cannot be null!"); } return new ResolvingGrammarGenerator().generate(writer, reader); }
@Override protected void encode(Encoder e, Schema s, JsonNode n) throws IOException { ResolvingGrammarGenerator.encode(e, s, n); } });
if (rf == null) { production[--count] = Symbol.skipAction(generate(wf.schema(), wf.schema(), seen)); } else { production[--count] = generate(wf.schema(), rf.schema(), seen); Field wf = writer.getField(fname); if (wf == null) { 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;
private Symbol resolveUnion(Schema writer, Schema reader, Map<LitS, Symbol> seen) throws IOException { boolean needsAdj = ! unionEquiv(writer, reader, new HashMap<>()); List<Schema> alts2 = (!needsAdj ? reader.getTypes() : null); List<Schema> alts = writer.getTypes(); final int size = alts.size(); Symbol[] symbols = new Symbol[size]; String[] labels = new String[size]; /** * We construct a symbol without filling the arrays. Please see * {@link Symbol#production} for the reason. */ int i = 0; for (Schema w : alts) { symbols[i] = generate(w, (needsAdj ? reader : alts2.get(i)), seen); labels[i] = w.getFullName(); i++; } if (! needsAdj) return Symbol.seq(Symbol.alt(symbols, labels), Symbol.UNION); return Symbol.seq(Symbol.alt(symbols, labels), Symbol.WRITER_UNION_ACTION); }
!hasMatchError(resolveRecords(w, b, seen))) { String vShortName = w.getName(); String bShortName = b.getName();
if (writer.getFullName() == null || writer.getFullName().equals(reader.getFullName())) { return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(), reader.getEnumSymbols()), Symbol.ENUM); generate(writer.getElementType(), reader.getElementType(), seen)), Symbol.ARRAY_START); generate(writer.getValueType(), reader.getValueType(), seen), Symbol.STRING), Symbol.MAP_START); case RECORD: return resolveRecords(writer, reader, seen); case UNION: return resolveUnion(writer, reader, seen); default: throw new AvroTypeException("Unkown type for schema: " + writerType); return resolveUnion(writer, reader, seen); int j = bestBranch(reader, writer, seen); if (j >= 0) { Symbol s = generate(writer, reader.getTypes().get(j), seen); return Symbol.seq(Symbol.unionAdjustAction(j, s), Symbol.UNION);
/** * Resolves the writer schema <tt>writer</tt> and the reader schema * <tt>reader</tt> and returns the start symbol for the grammar generated. * @param writer The schema used by the writer * @param reader The schema used by the reader * @return The start symbol for the resolving grammar * @throws IOException */ public final Symbol generate(Schema writer, Schema reader) throws IOException { return Symbol.root(generate(writer, reader, new HashMap<>())); }
if (writer.getFullName() == null || writer.getFullName().equals(reader.getFullName())) { return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(), reader.getEnumSymbols(), reader.getEnumDefault()), Symbol.ENUM); generate(writer.getElementType(), reader.getElementType(), seen)), Symbol.ARRAY_START); generate(writer.getValueType(), reader.getValueType(), seen), Symbol.STRING), Symbol.MAP_START); case RECORD: return resolveRecords(writer, reader, seen); case UNION: return resolveUnion(writer, reader, seen); default: throw new AvroTypeException("Unknown type for schema: " + writerType); return resolveUnion(writer, reader, seen); int j = firstMatchingBranch(reader, writer, seen); if (j >= 0) { Symbol s = generate(writer, reader.getTypes().get(j), seen); return Symbol.seq(Symbol.unionAdjustAction(j, s), Symbol.UNION);
if (writer.getName() == null || writer.getName().equals(reader.getName())) { return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(), reader.getEnumSymbols()), Symbol.ENUM); generate(writer.getElementType(), reader.getElementType(), seen)), Symbol.ARRAY_START); generate(writer.getValueType(), reader.getValueType(), seen), Symbol.STRING), Symbol.MAP_START); case RECORD: return resolveRecords(writer, reader, seen); case UNION: return resolveUnion(writer, reader, seen); default: throw new AvroTypeException("Unkown type for schema: " + writerType); return resolveUnion(writer, reader, seen); int j = bestBranch(reader, writer); if (j >= 0) { Symbol s = generate(writer, reader.getTypes().get(j), seen); return Symbol.seq(new Symbol.UnionAdjustAction(j, s), Symbol.UNION);
/** * Resolves the writer schema <tt>writer</tt> and the reader schema * <tt>reader</tt> and returns the start symbol for the grammar generated. * @param writer The schema used by the writer * @param reader The schema used by the reader * @return The start symbol for the resolving grammar * @throws IOException */ public final Symbol generate(Schema writer, Schema reader) throws IOException { return Symbol.root(generate(writer, reader, new HashMap<LitS, Symbol>())); }
!hasMatchError(resolveRecords(w, b, seen))) { String vShortName = w.getName(); String bShortName = b.getName();
/** * Produces an opaque resolver that can be used to construct a new * {@link ResolvingDecoder#ResolvingDecoder(Object, Decoder)}. The * returned Object is immutable and hence can be simultaneously used * in many ResolvingDecoders. This method is reasonably expensive, the * users are encouraged to cache the result. * * @param writer The writer's schema. Cannot be null. * @param reader The reader's schema. Cannot be null. * @return The opaque reolver. * @throws IOException */ public static Object resolve(Schema writer, Schema reader) throws IOException { if (null == writer) { throw new NullPointerException("writer cannot be null!"); } if (null == reader) { throw new NullPointerException("reader cannot be null!"); } return new ResolvingGrammarGenerator().generate(writer, reader); }
if (writer.getName() == null || writer.getName().equals(reader.getName())) { return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(), reader.getEnumSymbols()), Symbol.ENUM); generate(writer.getElementType(), reader.getElementType(), seen)), Symbol.ARRAY_START); generate(writer.getValueType(), reader.getValueType(), seen), Symbol.STRING), Symbol.MAP_START); case RECORD: return resolveRecords(writer, reader, seen); case UNION: return resolveUnion(writer, reader, seen); default: throw new AvroTypeException("Unkown type for schema: " + writerType); return resolveUnion(writer, reader, seen); int j = bestBranch(reader, writer); if (j >= 0) { Symbol s = generate(writer, reader.getTypes().get(j), seen); return Symbol.seq(new Symbol.UnionAdjustAction(j, s), Symbol.UNION);
if (rf == null) { production[--count] = Symbol.skipAction(generate(wf.schema(), wf.schema(), seen)); } else { production[--count] = generate(wf.schema(), rf.schema(), seen); Field wf = writer.getField(fname); if (wf == null) { byte[] bb = getBinary(rf.schema(), rf.defaultValue()); production[--count] = Symbol.defaultStartAction(bb); production[--count] = generate(rf.schema(), rf.schema(), seen); production[--count] = Symbol.DEFAULT_END_ACTION;
private Symbol resolveUnion(Schema writer, Schema reader, Map<LitS, Symbol> seen) throws IOException { List<Schema> alts = writer.getTypes(); final int size = alts.size(); Symbol[] symbols = new Symbol[size]; String[] labels = new String[size]; /** * We construct a symbol without filling the arrays. Please see * {@link Symbol#production} for the reason. */ int i = 0; for (Schema w : alts) { symbols[i] = generate(w, reader, seen); labels[i] = w.getFullName(); i++; } return Symbol.seq(Symbol.alt(symbols, labels), Symbol.writerUnionAction()); }
/** * Returns the Avro binary encoded version of <tt>n</tt> according to * the schema <tt>s</tt>. * @param s The schema for encoding * @param n The Json node that has the value to be encoded. * @return The binary encoded version of <tt>n</tt>. * @throws IOException */ private static byte[] getBinary(Schema s, JsonNode n) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); Encoder e = factory.binaryEncoder(out, null); encode(e, s, n); e.flush(); return out.toByteArray(); }
!hasMatchError(resolveRecords(w, b, seen))) { String vShortName = w.getName(); String bShortName = b.getName();
/** * Validates that data written with one schema can be read using another, * based on the default Avro schema resolution rules. * * @param writtenWith * The "writer's" schema, representing data to be read. * @param readUsing * The "reader's" schema, representing how the reader will interpret * data. * @throws SchemaValidationException * if the schema <b>readUsing<b/> cannot be used to read data * written with <b>writtenWith<b/> */ static void canRead(Schema writtenWith, Schema readUsing) throws SchemaValidationException { boolean error; try { error = Symbol.hasErrors(new ResolvingGrammarGenerator().generate( writtenWith, readUsing)); } catch (IOException e) { throw new SchemaValidationException(readUsing, writtenWith, e); } if (error) { throw new SchemaValidationException(readUsing, writtenWith); } }
if (writer.getFullName() == null || writer.getFullName().equals(reader.getFullName())) { return Symbol.seq(mkEnumAdjust(writer.getEnumSymbols(), reader.getEnumSymbols()), Symbol.ENUM); generate(writer.getElementType(), reader.getElementType(), seen)), Symbol.ARRAY_START); generate(writer.getValueType(), reader.getValueType(), seen), Symbol.STRING), Symbol.MAP_START); case RECORD: return resolveRecords(writer, reader, seen); case UNION: return resolveUnion(writer, reader, seen); default: throw new AvroTypeException("Unkown type for schema: " + writerType); return resolveUnion(writer, reader, seen); int j = bestBranch(reader, writer); if (j >= 0) { Symbol s = generate(writer, reader.getTypes().get(j), seen); return Symbol.seq(Symbol.unionAdjustAction(j, s), Symbol.UNION);
if (rf == null) { production[--count] = new Symbol.SkipAction(generate(wf.schema(), wf.schema(), seen)); } else { production[--count] = generate(wf.schema(), rf.schema(), seen); Field wf = writer.getField(fname); if (wf == null) { byte[] bb = getBinary(rf.schema(), rf.defaultValue()); production[--count] = new Symbol.DefaultStartAction(bb); production[--count] = generate(rf.schema(), rf.schema(), seen); production[--count] = Symbol.DEFAULT_END_ACTION;