Skip to content

Commit

Permalink
Added more tests and fixed a couple of bugs. Also formatted the code
Browse files Browse the repository at this point in the history
  • Loading branch information
thiru-aqfer committed Apr 30, 2017
1 parent ce0bad5 commit 9132015
Show file tree
Hide file tree
Showing 11 changed files with 552 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* this visitor will create a clone of the original Schema and will also resolve all unresolved schemas
*
* by default. what attributes are copied is customizable.
* @author zoly
*/
public final class ResolvingVisitor implements SchemaVisitor<Schema> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
package org.apache.avro.compiler.idl;

import avro.shaded.com.google.common.base.Function;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.apache.avro.Protocol;
import org.apache.avro.Schema;
import org.apache.avro.compiler.schema.Schemas;
Expand All @@ -44,46 +46,45 @@ private SchemaResolver() {
* Create a schema to represent a "unresolved" schema.
* (used to represent a schema where the definition is not known at the time)
* This concept might be generalizable...
*
* @param name
* @return
*/
static Schema unresolvedSchema(final String name) {
Schema schema = Schema.createRecord(UR_SCHEMA_NAME, "unresolved schema",
UR_SCHEMA_NS, false, Collections.EMPTY_LIST);
UR_SCHEMA_NS, false, Collections.EMPTY_LIST);
schema.addProp(UR_SCHEMA_ATTR, name);
return schema;
}

/**
* Is this a unresolved schema.
*
* @param schema
* @return
*/
static boolean isUnresolvedSchema(final Schema schema) {
return (schema.getType() == Schema.Type.RECORD && schema.getProp(UR_SCHEMA_ATTR) != null
&& UR_SCHEMA_NAME.equals(schema.getName())
&& UR_SCHEMA_NS.equals(schema.getNamespace()));
&& UR_SCHEMA_NAME.equals(schema.getName())
&& UR_SCHEMA_NS.equals(schema.getNamespace()));
}

/**
* get the unresolved schema name.
*
* @param schema
* @return
*/
static String getUnresolvedSchemaName(final Schema schema) {
if (!isUnresolvedSchema(schema)) {
throw new IllegalArgumentException("Not a unresolved schema: " + schema);
}
String name = schema.getProp(UR_SCHEMA_ATTR);
if (name == null) {
throw new IllegalArgumentException("Schema " + schema + " must have attribute: " + UR_SCHEMA_ATTR);
} else {
return name;
}
return schema.getProp(UR_SCHEMA_ATTR);
}

/**
* Will clone the provided protocol while resolving all unreferenced schemas
*
* @param protocol
* @return
*/
Expand All @@ -105,13 +106,13 @@ static Protocol resolve(final Protocol protocol) {
if (value.isOneWay()) {
Schema replacement = resolve(replacements, value.getRequest(), protocol);
nvalue = result.createMessage(value.getName(), value.getDoc(),
value.getObjectProps(), replacement);
value.getObjectProps(), replacement);
} else {
Schema request = resolve(replacements, value.getRequest(), protocol);
Schema response = resolve(replacements, value.getResponse(), protocol);
Schema errors = resolve(replacements, value.getErrors(), protocol);
nvalue = result.createMessage(value.getName(), value.getDoc(),
value.getObjectProps(), request, response, errors);
value.getObjectProps(), request, response, errors);
}
result.getMessages().put(entry.getKey(), nvalue);
}
Expand All @@ -120,11 +121,11 @@ static Protocol resolve(final Protocol protocol) {
}

private static Schema resolve(final IdentityHashMap<Schema, Schema> replacements,
final Schema request, final Protocol protocol) {
final Schema request, final Protocol protocol) {
Schema replacement = replacements.get(request);
if (replacement == null) {
replacement = Schemas.visit(request, new ResolvingVisitor(request, replacements,
new SymbolTable(protocol)));
new SymbolTable(protocol)));
}
return replacement;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;

import org.apache.avro.Schema;

import static org.apache.avro.Schema.Type.RECORD;

/**
* this visitor will create a clone of the original Schema with docs and other nonesential fields stripped
* by default. what attributes are copied is customizable.
* @author zoly
*/
public final class CloningVisitor implements SchemaVisitor<Schema> {

Expand All @@ -24,11 +25,13 @@ public final class CloningVisitor implements SchemaVisitor<Schema> {

public interface PropertyCopier {
void copy(Schema first, Schema second);

void copy(Schema.Field first, Schema.Field second);
}

/**
* copy only serialization necessary fields.
*
* @param root
*/
public CloningVisitor(final Schema root) {
Expand All @@ -41,7 +44,7 @@ public void copy(final Schema first, final Schema second) {

@Override
public void copy(final Schema.Field first, final Schema.Field second) {
Schemas.copyAliases(first, second);
Schemas.copyAliases(first, second);
}
}, false, root);
}
Expand Down Expand Up @@ -74,14 +77,14 @@ public SchemaVisitorAction visitTerminal(final Schema terminal) {
case NULL:
case STRING:
newSchema = Schema.create(type);
break;
break;
case ENUM:
newSchema = Schema.createEnum(terminal.getName(), copyDocs ? terminal.getDoc() : null,
terminal.getNamespace(), terminal.getEnumSymbols());
terminal.getNamespace(), terminal.getEnumSymbols());
break;
case FIXED:
newSchema = Schema.createFixed(terminal.getName(), copyDocs ? terminal.getDoc() : null,
terminal.getNamespace(), terminal.getFixedSize());
terminal.getNamespace(), terminal.getFixedSize());
break;
default:
throw new IllegalStateException("Unsupported schema " + terminal);
Expand All @@ -94,52 +97,52 @@ public SchemaVisitorAction visitTerminal(final Schema terminal) {
@Override
public SchemaVisitorAction visitNonTerminal(final Schema nt) {
Schema.Type type = nt.getType();
if (type == RECORD) {
Schema newSchema = Schema.createRecord(nt.getName(), copyDocs ? nt.getDoc() : null,
nt.getNamespace(), nt.isError());
copyProperties.copy(nt, newSchema);
replace.put(nt, newSchema);
if (type == RECORD) {
Schema newSchema = Schema.createRecord(nt.getName(), copyDocs ? nt.getDoc() : null,
nt.getNamespace(), nt.isError());
copyProperties.copy(nt, newSchema);
replace.put(nt, newSchema);
}
return SchemaVisitorAction.CONTINUE;
}

@Override
public SchemaVisitorAction afterVisitNonTerminal(final Schema nt) {
Schema.Type type = nt.getType();
Schema newSchema;
switch (type) {
case RECORD:
newSchema = replace.get(nt);
List<Schema.Field> fields = nt.getFields();
List<Schema.Field> newFields = new ArrayList<Schema.Field>(fields.size());
for (Schema.Field field : fields) {
Schema.Type type = nt.getType();
Schema newSchema;
switch (type) {
case RECORD:
newSchema = replace.get(nt);
List<Schema.Field> fields = nt.getFields();
List<Schema.Field> newFields = new ArrayList<Schema.Field>(fields.size());
for (Schema.Field field : fields) {
Schema.Field newField = new Schema.Field(field.name(), replace.get(field.schema()),
copyDocs ? field.doc() : null, field.defaultVal(), field.order());
copyDocs ? field.doc() : null, field.defaultVal(), field.order());
copyProperties.copy(field, newField);
newFields.add(newField);
}
newSchema.setFields(newFields);
return SchemaVisitorAction.CONTINUE;
case UNION:
List<Schema> types = nt.getTypes();
List<Schema> newTypes = new ArrayList<Schema>(types.size());
for (Schema sch : types) {
newTypes.add(replace.get(sch));
}
newSchema = Schema.createUnion(newTypes);
break;
case ARRAY:
newSchema = Schema.createArray(replace.get(nt.getElementType()));
break;
case MAP:
newSchema = Schema.createMap(replace.get(nt.getValueType()));
break;
default:
throw new IllegalStateException("Illegal type " + type + ", schema " + nt);
}
copyProperties.copy(nt, newSchema);
replace.put(nt, newSchema);
return SchemaVisitorAction.CONTINUE;
}
newSchema.setFields(newFields);
return SchemaVisitorAction.CONTINUE;
case UNION:
List<Schema> types = nt.getTypes();
List<Schema> newTypes = new ArrayList<Schema>(types.size());
for (Schema sch : types) {
newTypes.add(replace.get(sch));
}
newSchema = Schema.createUnion(newTypes);
break;
case ARRAY:
newSchema = Schema.createArray(replace.get(nt.getElementType()));
break;
case MAP:
newSchema = Schema.createMap(replace.get(nt.getValueType()));
break;
default:
throw new IllegalStateException("Illegal type " + type + ", schema " + nt);
}
copyProperties.copy(nt, newSchema);
replace.put(nt, newSchema);
return SchemaVisitorAction.CONTINUE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
/*
* Copyright (c) 2001 - 2016, Zoltan Farkas All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Copyright (c) 2001 - 2016, Zoltan Farkas All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.apache.avro.compiler.schema;

import org.apache.avro.Schema;

/**
* @author zoly
*/
public interface SchemaVisitor<T> {

/**
* Invoked for schemas that do not have "child" schemas (like string, int ...)
* or for a previously encountered schema with children,
* which will be treated as a terminal. (to avoid circular recursion)
*
* @param terminal
* @return
*/
SchemaVisitorAction visitTerminal(Schema terminal);

/**
* Invoked for schema with children before proceeding to visit the children.
*
* @param nonTerminal
* @return
*/
SchemaVisitorAction visitNonTerminal(Schema nonTerminal);

/**
* Invoked for schemas with children after its children have been visited.
*
* @param nonTerminal
* @return
*/
Expand All @@ -50,6 +50,7 @@ public interface SchemaVisitor<T> {

/**
* Invoked when visiting is complete.
*
* @return a value which will be returned by the visit method.
*/
T get();
Expand Down
Loading

0 comments on commit 9132015

Please sign in to comment.