use of com.linkedin.avroutil1.model.AvroName in project avro-util by linkedin.
the class AvscWriter method aliasesToJson.
protected void aliasesToJson(Schema schema, List<AvroName> extraAliases, G gen) throws IOException {
Set<String> userDefinedAliases = schema.getAliases();
// could be null
Set<String> allAliases = userDefinedAliases;
if (addAliasesForAvro702 && extraAliases != null) {
allAliases = new HashSet<>();
if (userDefinedAliases != null) {
allAliases.addAll(userDefinedAliases);
}
for (AvroName extraAlias : extraAliases) {
allAliases.add(extraAlias.getFull());
}
}
if (allAliases == null || allAliases.isEmpty()) {
return;
}
AvroName name = AvroName.of(schema);
// "context" namespace for aliases is the fullname of the names type on which they are defined
// except for the extra alias. scenarios where extraAlias is used are those where the "effective"
// name of this schema (or its correct form) is different to its full name, so we want
// to very explicitly use the fullname of the alias for those.
String referenceNamespace = name.getSpace();
gen.writeFieldName("aliases");
gen.writeStartArray();
// add yet more aliases to account for those!
for (String s : allAliases) {
AvroName alias = new AvroName(s, null);
if (addAliasesForAvro702 && extraAliases != null && extraAliases.contains(alias)) {
// always emit any avro-702 related aliases as fullnames
gen.writeString(alias.getFull());
} else {
String relative = alias.getQualified(referenceNamespace);
gen.writeString(relative);
}
}
gen.writeEndArray();
}
use of com.linkedin.avroutil1.model.AvroName in project avro-util by linkedin.
the class AvscSchemaWriter method emitSchemaAliases.
protected void emitSchemaAliases(AvroNamedSchema schema, AvscWriterContext context, AvscWriterConfig config, AvroName extraAlias, JsonObjectBuilder output) {
List<AvroName> aliases = schema.getAliases();
int numAliases = (extraAlias != null ? 1 : 0) + (aliases != null ? aliases.size() : 0);
if (numAliases == 0) {
return;
}
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
if (aliases != null) {
for (AvroName alias : aliases) {
arrayBuilder.add(alias.getFullname());
}
}
if (extraAlias != null) {
arrayBuilder.add(extraAlias.getFullname());
}
output.add("aliases", arrayBuilder);
}
use of com.linkedin.avroutil1.model.AvroName in project avro-util by linkedin.
the class AvscSchemaWriter method pathForSchema.
protected Path pathForSchema(AvroSchema maybeNamed) {
if (!(maybeNamed instanceof AvroNamedSchema)) {
return null;
}
AvroNamedSchema namedSchema = (AvroNamedSchema) maybeNamed;
AvroName name = namedSchema.getName();
if (!name.hasNamespace()) {
return Paths.get(name.getSimpleName() + "." + AvscFile.SUFFIX);
}
String fullname = name.getFullname();
String[] parts = fullname.split("\\.");
String[] pathParts = new String[parts.length - 1];
for (int i = 1; i < parts.length; i++) {
if (i == parts.length - 1) {
pathParts[i - 1] = parts[i] + "." + AvscFile.SUFFIX;
} else {
pathParts[i - 1] = parts[i];
}
}
return Paths.get(parts[0], pathParts);
}
use of com.linkedin.avroutil1.model.AvroName in project avro-util by linkedin.
the class AvscParser method parseSchemaName.
private AvroName parseSchemaName(JsonObjectExt objectNode, AvscFileParseContext context, AvroType avroType) {
Located<String> nameStr = getRequiredString(objectNode, "name", () -> avroType + " is a named type");
Located<String> namespaceStr = getOptionalString(objectNode, "namespace");
String name = nameStr.getValue();
String namespace = namespaceStr != null ? namespaceStr.getValue() : null;
AvroName schemaName;
if (name.contains(".")) {
// the name specified is a full name (namespace included)
context.addIssue(AvscIssues.useOfFullName(new CodeLocation(context.getUri(), nameStr.getLocation(), nameStr.getLocation()), avroType, name));
if (namespace != null) {
// namespace will be ignored, but it's confusing to even list it
context.addIssue(AvscIssues.ignoredNamespace(new CodeLocation(context.getUri(), namespaceStr.getLocation(), namespaceStr.getLocation()), avroType, namespace, name));
}
// TODO - validate names (no ending in dot, no spaces, etc)
int lastDot = name.lastIndexOf('.');
schemaName = new AvroName(name.substring(lastDot + 1), name.substring(0, lastDot));
} else {
String inheritedNamespace = namespace != null ? namespace : context.getCurrentNamespace();
schemaName = new AvroName(name, inheritedNamespace);
}
return schemaName;
}
use of com.linkedin.avroutil1.model.AvroName in project avro-util by linkedin.
the class AvscParser method parseNamedSchema.
private AvroNamedSchema parseNamedSchema(JsonObjectExt objectNode, AvscFileParseContext context, AvroType avroType, CodeLocation codeLocation, JsonPropertiesContainer extraProps) {
AvroName schemaName = parseSchemaName(objectNode, context, avroType);
List<AvroName> aliases = parseAliases(objectNode, context, avroType, schemaName);
// technically the avro spec does not allow "doc" on type fixed, but screw that
Located<String> docStr = getOptionalString(objectNode, "doc");
String doc = docStr != null ? docStr.getValue() : null;
boolean namespaceChanged = false;
// check if context namespace changed
if (!context.getCurrentNamespace().equals(schemaName.getNamespace())) {
context.pushNamespace(schemaName.getNamespace());
namespaceChanged = true;
}
AvroNamedSchema namedSchema;
switch(avroType) {
case RECORD:
AvroRecordSchema recordSchema = new AvroRecordSchema(codeLocation, schemaName, aliases, doc, extraProps);
JsonArrayExt fieldsNode = getRequiredArray(objectNode, "fields", () -> "all avro records must have fields");
List<AvroSchemaField> fields = new ArrayList<>(fieldsNode.size());
for (int fieldNum = 0; fieldNum < fieldsNode.size(); fieldNum++) {
// !=null
JsonValueExt fieldDeclNode = (JsonValueExt) fieldsNode.get(fieldNum);
JsonValue.ValueType fieldNodeType = fieldDeclNode.getValueType();
if (fieldNodeType != JsonValue.ValueType.OBJECT) {
throw new AvroSyntaxException("field " + fieldNum + " for record " + schemaName.getSimpleName() + " at " + fieldDeclNode.getStartLocation() + " expected to be an OBJECT, not a " + JsonPUtil.describe(fieldNodeType) + " (" + fieldDeclNode + ")");
}
TextLocation fieldStartLocation = Util.convertLocation(fieldDeclNode.getStartLocation());
TextLocation fieldEndLocation = Util.convertLocation(fieldDeclNode.getEndLocation());
CodeLocation fieldCodeLocation = new CodeLocation(context.getUri(), fieldStartLocation, fieldEndLocation);
JsonObjectExt fieldDecl = (JsonObjectExt) fieldDeclNode;
Located<String> fieldName = getRequiredString(fieldDecl, "name", () -> "all record fields must have a name");
JsonValueExt fieldTypeNode = getRequiredNode(fieldDecl, "type", () -> "all record fields must have a type");
Located<String> locatedDocField = getOptionalString(fieldDecl, "doc");
String docField = locatedDocField == null ? null : locatedDocField.getValue();
SchemaOrRef fieldSchema = parseSchemaDeclOrRef(fieldTypeNode, context, false);
JsonValueExt fieldDefaultValueNode = fieldDecl.get("default");
AvroLiteral defaultValue = null;
if (fieldDefaultValueNode != null) {
if (fieldSchema.isResolved()) {
LiteralOrIssue defaultValurOrIssue = parseLiteral(fieldDefaultValueNode, fieldSchema.getSchema(), fieldName.getValue(), context);
if (defaultValurOrIssue.getIssue() == null) {
defaultValue = defaultValurOrIssue.getLiteral();
}
// TODO - handle issues
} else {
// TODO - implement delayed default value parsing
throw new UnsupportedOperationException("delayed parsing of default value for " + fieldName.getValue() + " TBD");
}
}
LinkedHashMap<String, JsonValueExt> props = parseExtraProps(fieldDecl, CORE_FIELD_PROPERTIES);
JsonPropertiesContainer propsContainer = props.isEmpty() ? JsonPropertiesContainer.EMPTY : new JsonPropertiesContainerImpl(props);
AvroSchemaField field = new AvroSchemaField(fieldCodeLocation, fieldName.getValue(), docField, fieldSchema, defaultValue, propsContainer);
fields.add(field);
}
recordSchema.setFields(fields);
namedSchema = recordSchema;
break;
case ENUM:
JsonArrayExt symbolsNode = getRequiredArray(objectNode, "symbols", () -> "all avro enums must have symbols");
List<String> symbols = new ArrayList<>(symbolsNode.size());
for (int ordinal = 0; ordinal < symbolsNode.size(); ordinal++) {
JsonValueExt symbolNode = (JsonValueExt) symbolsNode.get(ordinal);
JsonValue.ValueType symbolNodeType = symbolNode.getValueType();
if (symbolNodeType != JsonValue.ValueType.STRING) {
throw new AvroSyntaxException("symbol " + ordinal + " for enum " + schemaName.getSimpleName() + " at " + symbolNode.getStartLocation() + " expected to be a STRING, not a " + JsonPUtil.describe(symbolNodeType) + " (" + symbolNode + ")");
}
symbols.add(symbolNode.toString());
}
String defaultSymbol = null;
Located<String> defaultStr = getOptionalString(objectNode, "default");
if (defaultStr != null) {
defaultSymbol = defaultStr.getValue();
if (!symbols.contains(defaultSymbol)) {
context.addIssue(AvscIssues.badEnumDefaultValue(locationOf(context.getUri(), defaultStr), defaultSymbol, schemaName.getSimpleName(), symbols));
// TODO - support "fixing" by selecting 1st symbol as default?
defaultSymbol = null;
}
}
namedSchema = new AvroEnumSchema(codeLocation, schemaName, aliases, doc, symbols, defaultSymbol, extraProps);
break;
case FIXED:
JsonValueExt sizeNode = getRequiredNode(objectNode, "size", () -> "fixed types must have a size property");
if (sizeNode.getValueType() != JsonValue.ValueType.NUMBER || !(((JsonNumberExt) sizeNode).isIntegral())) {
throw new AvroSyntaxException("size for fixed " + schemaName.getSimpleName() + " at " + sizeNode.getStartLocation() + " expected to be an INTEGER, not a " + JsonPUtil.describe(sizeNode.getValueType()) + " (" + sizeNode + ")");
}
int fixedSize = ((JsonNumberExt) sizeNode).intValue();
Parsed<AvroLogicalType> logicalTypeResult = parseLogicalType(objectNode, context, avroType, codeLocation);
if (logicalTypeResult.hasIssues()) {
context.addIssues(logicalTypeResult.getIssues());
}
namedSchema = new AvroFixedSchema(codeLocation, schemaName, aliases, doc, fixedSize, logicalTypeResult.getData(), extraProps);
break;
default:
throw new IllegalStateException("unhandled: " + avroType + " for object at " + codeLocation.getStart());
}
if (namespaceChanged) {
context.popNamespace();
}
return namedSchema;
}
Aggregations