Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.avro.avsc.Schemas Maven / Gradle / Ivy
Go to download
Avro adaptation (abstraction layer betwen zolyfarkas/avro and apache/avro) utils.
package org.apache.avro.avsc;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import org.apache.avro.JsonProperties;
import org.apache.avro.LogicalType;
import org.apache.avro.Schema;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.stream.Stream;
/**
* Avro Schema utilities, to traverse...
*/
public final class Schemas {
private Schemas() {
}
@SuppressWarnings("checkstyle:MissingSwitchDefault")
public static void copyAliases(final Schema from, final Schema to) {
switch (from.getType()) { // only named types.
case RECORD:
case ENUM:
case FIXED:
Set aliases = from.getAliases();
for (String alias : aliases) {
to.addAlias(alias);
}
}
}
public static void copyAliases(final Schema.Field from, final Schema.Field to) {
Set aliases = from.aliases();
for (String alias : aliases) {
to.addAlias(alias);
}
}
public static void copyLogicalTypes(final Schema from, final Schema to) {
LogicalType logicalType = from.getLogicalType();
if (logicalType != null) {
logicalType.addToSchema(to);
}
}
public static void copyProperties(final JsonProperties from, final JsonProperties to) {
Map objectProps = from.getObjectProps();
for (Map.Entry entry : objectProps.entrySet()) {
to.addProp(entry.getKey(), entry.getValue());
}
}
public static boolean hasGeneratedJavaClass(final Schema schema) {
Schema.Type type = schema.getType();
switch (type) {
case ENUM:
case RECORD:
case FIXED:
return true;
default:
return false;
}
}
public static String getJavaClassName(final Schema schema) {
String namespace = schema.getNamespace();
if (namespace == null) {
return mangle(schema.getName());
} else {
return namespace + '.' + mangle(schema.getName());
}
}
/**
* depth first visit.
*
* @param start
* @param visitor
*/
public static T visit(final Schema start, final SchemaVisitor visitor) {
// Set of Visited Schemas
IdentityHashMap visited = new IdentityHashMap();
// Stack that contains the Schams to process and afterVisitNonTerminal functions.
// Deque>>
// Using either has a cost which we want to avoid...
Deque dq = new ArrayDeque();
dq.addLast(start);
Object current;
while ((current = dq.pollLast()) != null) {
if (current instanceof Supplier) {
// we are executing a non terminal post visit.
SchemaVisitorAction action = ((Supplier) current).get();
switch (action) {
case CONTINUE:
break;
case SKIP_SUBTREE:
throw new UnsupportedOperationException();
case SKIP_SIBLINGS:
while (dq.getLast() instanceof Schema) {
dq.removeLast();
}
break;
case TERMINATE:
return visitor.get();
default:
throw new UnsupportedOperationException("Invalid action " + action);
}
} else {
Schema schema = (Schema) current;
boolean terminate;
if (!visited.containsKey(schema)) {
Schema.Type type = schema.getType();
switch (type) {
case ARRAY:
terminate = visitNonTerminal(visitor, schema, dq, Collections.singletonList(schema.getElementType()));
visited.put(schema, schema);
break;
case RECORD:
List fields = schema.getFields();
int fsize = fields.size();
ListIterator it = fields.listIterator(fsize);
terminate = visitNonTerminal(visitor, schema, dq,
() -> Stream.generate(it::previous).limit(fsize).map(Schema.Field::schema).iterator());
visited.put(schema, schema);
break;
case UNION:
terminate = visitNonTerminal(visitor, schema, dq, schema.getTypes());
visited.put(schema, schema);
break;
case MAP:
terminate = visitNonTerminal(visitor, schema, dq, Collections.singletonList(schema.getValueType()));
visited.put(schema, schema);
break;
case NULL:
case BOOLEAN:
case BYTES:
case DOUBLE:
case ENUM:
case FIXED:
case FLOAT:
case INT:
case LONG:
case STRING:
terminate = visitTerminal(visitor, schema, dq);
break;
default:
throw new UnsupportedOperationException("Invalid type " + type);
}
} else {
terminate = visitTerminal(visitor, schema, dq);
}
if (terminate) {
return visitor.get();
}
}
}
return visitor.get();
}
private static boolean visitNonTerminal(final SchemaVisitor visitor,
final Schema schema, final Deque dq,
final Iterable itSupp) {
SchemaVisitorAction action = visitor.visitNonTerminal(schema);
switch (action) {
case CONTINUE:
dq.addLast(new Supplier() {
@Override
public SchemaVisitorAction get() {
return visitor.afterVisitNonTerminal(schema);
}
});
Iterator it = itSupp.iterator();
while (it.hasNext()) {
Schema child = it.next();
dq.addLast(child);
}
break;
case SKIP_SUBTREE:
break;
case SKIP_SIBLINGS:
while (!dq.isEmpty() && dq.getLast() instanceof Schema) {
dq.removeLast();
}
break;
case TERMINATE:
return true;
default:
throw new UnsupportedOperationException("Invalid action " + action + " for " + schema);
}
return false;
}
private static boolean visitTerminal(final SchemaVisitor visitor, final Schema schema,
final Deque dq) {
SchemaVisitorAction action = visitor.visitTerminal(schema);
switch (action) {
case CONTINUE:
break;
case SKIP_SUBTREE:
throw new UnsupportedOperationException("Invalid action " + action + " for " + schema);
case SKIP_SIBLINGS:
while (!dq.isEmpty() && dq.getLast() instanceof Schema) {
dq.removeLast();
}
break;
case TERMINATE:
return true;
default:
throw new UnsupportedOperationException("Invalid action " + action + " for " + schema);
}
return false;
}
/** Utility for template use. Adds a dollar sign to reserved words. */
public static String mangle(final String word) {
return mangle(word, Collections.EMPTY_SET);
}
/** Utility for template use. Adds a dollar sign to reserved words. */
public static String mangle(final String word, final Set reservedWords) {
return mangle(word, reservedWords, false);
}
/** Utility for template use. Adds a dollar sign to reserved words. */
public static String mangle(final String word, final Set reservedWords,
final boolean isMethod) {
if (word.contains(".")) {
// If the 'word' is really a full path of a class we must mangle just the classname
int lastDot = word.lastIndexOf('.');
String packageName = word.substring(0, lastDot + 1);
String className = word.substring(lastDot + 1);
return packageName + mangle(className, reservedWords, isMethod);
}
if (reservedWords.contains(word)
|| (isMethod && reservedWords.contains(
Character.toLowerCase(word.charAt(0))
+ ((word.length() > 1) ? word.substring(1) : "")))) {
return word + "$";
}
return word;
}
}