package com.ctriposs.baiji.schema;
import com.ctriposs.baiji.exception.BaijiRuntimeException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public abstract class NamedSchema extends Schema {
private final SchemaName _schemaName;
private final String _doc;
private final List<SchemaName> _aliases;
/**
* Constructor for named schema class.
*
* @param type
* @param schemaName
* @param doc
* @param aliases
* @param props
* @param names list of named schemas already read
*/
protected NamedSchema(SchemaType type, SchemaName schemaName, String doc, List<SchemaName> aliases,
PropertyMap props, SchemaNames names) {
super(type, props);
_schemaName = schemaName;
_doc = doc;
_aliases = aliases;
if (schemaName.getName() != null && !names.add(schemaName, this)) {
throw new BaijiRuntimeException("Duplicated schema name " + schemaName.getFullName());
}
}
public SchemaName getSchemaName() {
return _schemaName;
}
@Override
public String getName() {
return _schemaName.getName();
}
public String getNamespace() {
return _schemaName.getNamespace();
}
public String getFullName() {
return _schemaName.getFullName();
}
public String getDoc() {
return _doc;
}
static NamedSchema newInstance(JsonNode node, PropertyMap props, SchemaNames names,
String encSpace) {
String type = JsonHelper.getRequiredString(node, "type");
if ("enum".equals(type)) {
return EnumSchema.newInstance(node, props, names, encSpace);
} else if ("record".equals(type)) {
return RecordSchema.newInstance(node, props, names, encSpace);
} else {
return names.getSchema(type, null, encSpace);
}
}
/**
* Parses the name and namespace from the given JSON schema object then creates
* SchemaName object including the given enclosing namespace
*
* @param node JSON object to read
* @param encspace JSON object to read
* @return
*/
protected static SchemaName getName(JsonNode node, String encspace) {
String n = JsonHelper.getOptionalString(node, "name");
// Changed this to optional string for anonymous records in messages
String ns = JsonHelper.getOptionalString(node, "namespace");
return new SchemaName(n, ns, encspace);
}
/**
* Writes named schema in JSON format
*
* @param gen JSON generator
* @param names list of named schemas already written
* @param encSpace enclosing namespace of the schema
*/
@Override
protected void writeJson(JsonGenerator gen, SchemaNames names, String encSpace)
throws IOException {
if (!names.add(this)) {
// schema is already in the list, write name only
SchemaName schemaName = getSchemaName();
String name;
if (schemaName.getNamespace() != encSpace) {
name = schemaName.getNamespace() + "." + schemaName.getName();
// we need to add the qualifying namespace of the target schema if it's not the same as current namespace
} else {
name = schemaName.getName();
}
gen.writeString(name);
} else {
// schema is not in the list, write full schema definition
super.writeJson(gen, names, encSpace);
}
}
/**
* Writes named schema in JSON format
*
* @param gen JSON generator
* @param names list of named schemas already written
* @param encSpace enclosing namespace of the schema
*/
@Override
protected void writeJsonFields(JsonGenerator gen, SchemaNames names, String encSpace) throws IOException {
_schemaName.writeJson(gen, names);
if (_doc != null && !_doc.isEmpty()) {
gen.writeFieldName("doc");
gen.writeString(_doc);
}
if (_aliases != null) {
gen.writeFieldName("aliases");
gen.writeStartArray();
for (SchemaName name : _aliases) {
String fullname = name.getSpace() != null ? name.getSpace() + "." + name.getName() : name.getName();
gen.writeString(fullname);
}
gen.writeEndArray();
}
}
/**
* Parses the 'aliases' property from the given JSON token
*
* @param node JSON object to read
* @param space namespace of the name this alias is for
* @param encSpace enclosing namespace of the name this alias is for
* @return List of SchemaName that represents the list of alias. If no 'aliases' specified, then it returns null.
*/
protected static List<SchemaName> getAliases(JsonNode node, String space, String encSpace) {
JsonNode aliasesNode = node.get("aliases");
if (aliasesNode == null) {
return null;
}
if (!aliasesNode.isArray()) {
throw new SchemaParseException("Aliases must be of format JSON array of strings");
}
List<SchemaName> aliases = new ArrayList<SchemaName>();
for (JsonNode aliasNode : aliasesNode) {
if (!aliasNode.isTextual()) {
throw new SchemaParseException("Aliases must be of format JSON array of strings");
}
aliases.add(new SchemaName(aliasNode.getTextValue(), space, encSpace));
}
return aliases;
}
protected boolean inAliases(SchemaName name) {
if (_aliases == null) {
return false;
}
for (SchemaName alias : _aliases) {
if (name.equals(alias)) {
return true;
}
}
return false;
}
}