com.atlassian.json.schema.AbstractJsonSchemaGenerator Maven / Gradle / Ivy
package com.atlassian.json.schema;
import java.lang.reflect.Field;
import java.util.*;
import com.atlassian.json.schema.annotation.*;
import com.atlassian.json.schema.doclet.model.JsonSchemaDocs;
import com.atlassian.json.schema.doclet.model.SchemaClassDoc;
import com.atlassian.json.schema.doclet.model.SchemaFieldDoc;
import com.atlassian.json.schema.model.*;
import com.atlassian.json.schema.scanner.model.InterfaceList;
import com.atlassian.json.schema.util.ReflectionUtil;
import com.atlassian.json.schema.util.StringUtil;
import static com.atlassian.json.schema.util.StringUtil.isNotBlank;
public abstract class AbstractJsonSchemaGenerator implements JsonSchemaGenerator
{
public static final String DEFINITION_PREFIX = "#/definitions/";
protected final EnumCase enumCase;
protected final InterfaceList interfaceList;
protected final JsonSchemaDocs schemaDocs;
protected final String ignoreFilter;
protected final Map definitions;
protected final String shortClassnameField;
protected AbstractJsonSchemaGenerator(EnumCase enumCase, InterfaceList interfaceList, JsonSchemaDocs schemaDocs, String ignoreFilter, String shortClassnameField)
{
this.enumCase = enumCase;
this.interfaceList = interfaceList;
this.schemaDocs = schemaDocs;
this.definitions = new HashMap();
if (null == ignoreFilter)
{
this.ignoreFilter = "";
}
else
{
this.ignoreFilter = ignoreFilter;
}
this.shortClassnameField = shortClassnameField;
}
@Override
public JsonSchema generateSchema(Class> rootClass)
{
BasicSchema rootSchema = (BasicSchema) generateSchemaForClass(rootClass, null);
String schemaUri = DollarSchema.DRAFTV4;
if (rootClass.isAnnotationPresent(DollarSchemaUri.class))
{
schemaUri = rootClass.getAnnotation(DollarSchemaUri.class).value();
}
rootSchema.addDollarSchema(schemaUri);
addDefinitionsToRoot(rootSchema);
return rootSchema;
}
protected void addDefinitionsToRoot(BasicSchema rootSchema)
{
if(null != definitions && !definitions.isEmpty())
{
rootSchema.setDefinitions(definitions);
}
}
protected JsonSchema generateSchemaForClass(Class> clazz, Field field)
{
if (SchemaTypesHelper.isMappedType(clazz))
{
return processSimpleType(clazz, field);
}
if (Map.class.isAssignableFrom(clazz))
{
return generateMapSchema(clazz, field);
}
if (Collection.class.isAssignableFrom(clazz))
{
return generateArraySchema(clazz, field, null);
}
if (clazz.isEnum())
{
return generateEnumSchema(clazz, field);
}
if (clazz.isInterface())
{
return generateInterfaceSchema(clazz, field);
}
return generateObjectSchema(clazz, field);
}
protected JsonSchema generateObjectSchema(Class> clazz, Field field, Class>... ifaces)
{
ObjectSchema schema = new ObjectSchema();
String definitionName = getDefinitionName(clazz);
if (StringUtil.isNotBlank(definitionName) && definitions.containsKey(definitionName))
{
BasicSchema refSchema = new BasicSchema();
refSchema.setRef(DEFINITION_PREFIX + definitionName);
return refSchema;
}
addCommonAttrsForField(schema, field);
addObjectAttrsForClass(schema, clazz);
addDocsForClass(schema, clazz);
Map props = new HashMap();
for (Field propField : ReflectionUtil.getPropertiesForJson(clazz))
{
if (propField.isAnnotationPresent(SchemaIgnore.class))
{
String fieldIgnoreFilter = propField.getAnnotation(SchemaIgnore.class).value();
if (StringUtil.isBlank(fieldIgnoreFilter) || ignoreFilter.equals(fieldIgnoreFilter))
{
continue;
}
}
String defaultArrayTitle = getFieldTitle(clazz, propField);
JsonSchema fieldSchema = generateSchemaForField(clazz, propField, ifaces, defaultArrayTitle);
if (null != fieldSchema)
{
addDocsForField(fieldSchema, clazz, propField);
props.put(getFieldName(propField), fieldSchema);
}
if (propField.isAnnotationPresent(Required.class))
{
if (null == schema.getRequired())
{
HashSet required = new HashSet();
schema.setRequired(required);
}
schema.getRequired().add(propField.getName());
}
}
if(StringUtil.isNotBlank(shortClassnameField))
{
props.put(shortClassnameField,StringUtil.lowerCamel(clazz.getSimpleName()));
}
schema.setProperties(props);
if (StringUtil.isNotBlank(definitionName) && !definitions.containsKey(definitionName))
{
definitions.put(definitionName, schema);
if(null != field)
{
BasicSchema refSchema = new BasicSchema();
refSchema.setRef(DEFINITION_PREFIX + definitionName);
return refSchema;
}
}
return schema;
}
private String getDefinitionName(Class> clazz)
{
String defName = null;
if (clazz.isAnnotationPresent(SchemaDefinition.class))
{
defName = clazz.getAnnotation(SchemaDefinition.class).value();
if(StringUtil.isBlank(defName))
{
defName = StringUtil.lowerCamel(clazz.getSimpleName());
}
}
return defName;
}
protected String getFieldName(Field field)
{
return field.getName();
}
protected void addDocsForClass(JsonSchema schema, Class> theClass)
{
SchemaClassDoc classDoc = schemaDocs.getClassDoc(theClass.getName());
if (null != classDoc)
{
if (isNotBlank(classDoc.getClassTitle()))
{
schema.setTitle(classDoc.getClassTitle());
}
if (isNotBlank(classDoc.getClassDoc()))
{
schema.setDescription(classDoc.getClassDoc());
}
}
}
protected void addDocsForField(JsonSchema schema, Class> theClass, Field theField)
{
SchemaClassDoc classDoc = schemaDocs.getClassDoc(theClass.getName());
if (null != classDoc)
{
SchemaFieldDoc fieldDoc = classDoc.getFieldDoc(theField.getName());
if (null != fieldDoc)
{
if (isNotBlank(fieldDoc.getFieldTitle()))
{
schema.setFieldTitle(fieldDoc.getFieldTitle());
}
if (isNotBlank(fieldDoc.getFieldDocs()))
{
schema.setFieldDescription(fieldDoc.getFieldDocs());
}
}
}
}
protected String getFieldTitle(Class> theClass, Field theField)
{
SchemaClassDoc classDoc = schemaDocs.getClassDoc(theClass.getName());
String title = null;
if (null != classDoc)
{
SchemaFieldDoc fieldDoc = classDoc.getFieldDoc(theField.getName());
if (null != fieldDoc)
{
if (isNotBlank(fieldDoc.getFieldTitle()))
{
title = fieldDoc.getFieldTitle();
}
}
}
if (null == title)
{
if (theField.isAnnotationPresent(CommonSchemaAttributes.class))
{
title = theField.getAnnotation(CommonSchemaAttributes.class).title();
}
}
return title;
}
protected void addCommonAttrsForField(AbstractSchema schema, Field theField)
{
if (null == theField)
{
return;
}
if (theField.isAnnotationPresent(CommonSchemaAttributes.class))
{
CommonSchemaAttributes commonAnno = theField.getAnnotation(CommonSchemaAttributes.class);
if (StringUtil.isNotBlank(commonAnno.defaultValue()))
{
schema.setDefaultValue(commonAnno.defaultValue());
}
if (StringUtil.isNotBlank(commonAnno.title()))
{
schema.setTitle(commonAnno.title());
}
if (StringUtil.isNotBlank(commonAnno.description()))
{
schema.setDescription(commonAnno.description());
}
if (commonAnno.allOf().length > 0)
{
schema.setAllOf(generateSchemaSet(commonAnno.allOf()));
}
if (commonAnno.anyOf().length > 0)
{
schema.setAnyOf(generateSchemaSet(commonAnno.anyOf()));
}
if (commonAnno.oneOf().length > 0)
{
schema.setOneOf(generateSchemaSet(commonAnno.oneOf()));
}
if (!AnnotationHelper.EmptyClass.class.getName().equals(commonAnno.not().getName()))
{
schema.setNot(generateObjectSchema(commonAnno.not(), null));
}
}
}
protected void addStringAttrsForField(StringSchema schema, Field theField)
{
if (null == theField)
{
return;
}
if (theField.isAnnotationPresent(StringSchemaAttributes.class))
{
StringSchemaAttributes stringAnno = theField.getAnnotation(StringSchemaAttributes.class);
if (StringUtil.isNotBlank(stringAnno.format()))
{
schema.setFormat(stringAnno.format());
}
if (StringUtil.isNotBlank(stringAnno.pattern()))
{
schema.setPattern(stringAnno.pattern());
}
if (stringAnno.maxLength() != Integer.MAX_VALUE)
{
schema.setMaxLength(stringAnno.maxLength());
}
if (stringAnno.minLength() != Integer.MIN_VALUE)
{
schema.setMinLength(stringAnno.minLength());
}
}
}
protected void addNumericAttrsForField(NumericSchema schema, Field theField)
{
if (null == theField)
{
return;
}
if (theField.isAnnotationPresent(NumericSchemaAttributes.class))
{
NumericSchemaAttributes numericAnno = theField.getAnnotation(NumericSchemaAttributes.class);
if (numericAnno.maximum() != Double.MAX_VALUE)
{
schema.setMaximum(numericAnno.maximum());
schema.setExclusiveMaximum(numericAnno.exclusiveMaximum());
}
if (numericAnno.minimum() != Double.MIN_VALUE)
{
schema.setMaximum(numericAnno.maximum());
schema.setExclusiveMinimum(numericAnno.exclusiveMinimum());
}
if (numericAnno.multipleOf() != -1)
{
schema.setMultipleOf(numericAnno.multipleOf());
}
}
}
protected void addArrayAttrsForField(ArrayTypeSchema schema, Field theField)
{
if (null == theField)
{
return;
}
if (theField.isAnnotationPresent(ArraySchemaAttributes.class))
{
ArraySchemaAttributes arrayAnno = theField.getAnnotation(ArraySchemaAttributes.class);
if (arrayAnno.maxItems() != Integer.MAX_VALUE)
{
schema.setMaxItems(arrayAnno.maxItems());
}
if (arrayAnno.minItems() != Integer.MIN_VALUE)
{
schema.setMinItems(arrayAnno.minItems());
}
schema.setAdditionalItems(arrayAnno.additionalItems());
schema.setUniqueItems(arrayAnno.uniqueItems());
}
}
protected void addObjectAttrsForClass(ObjectSchema schema, Class theClass)
{
if (null == theClass)
{
return;
}
if (theClass.isAnnotationPresent(ObjectSchemaAttributes.class))
{
ObjectSchemaAttributes objAnno = (ObjectSchemaAttributes) theClass.getAnnotation(ObjectSchemaAttributes.class);
if (StringUtil.isNotBlank(objAnno.id()))
{
schema.setId(objAnno.id());
}
if (objAnno.maxProperties() != Integer.MAX_VALUE)
{
schema.setMaxProperties(objAnno.maxProperties());
}
if (objAnno.minProperties() != Integer.MIN_VALUE)
{
schema.setMinProperties(objAnno.minProperties());
}
if (objAnno.patternProperties().length > 0)
{
Set patternProps = new HashSet(objAnno.patternProperties().length);
for (String pattern : objAnno.patternProperties())
{
patternProps.add(pattern);
}
schema.setPatternProperties(patternProps);
}
schema.setAdditionalProperties(objAnno.additionalProperties());
if (objAnno.dependencies().length > 0)
{
Map> deps = new HashMap>(objAnno.dependencies().length);
for (SchemaDependency dep : objAnno.dependencies())
{
deps.put(dep.property(), new HashSet(Arrays.asList(dep.requires())));
}
schema.setDependencies(deps);
}
}
}
protected Set generateSchemaSet(Class[] classes)
{
Set schemas = new HashSet(classes.length);
for (Class clazz : classes)
{
if (clazz.isInterface())
{
schemas.add(generateInterfaceSchema(clazz, null));
}
else
{
schemas.add(generateObjectSchema(clazz, null));
}
}
return schemas;
}
protected abstract JsonSchema generateSchemaForField(Class> clazz, Field field, Class>[] ifaces, String defaultArrayTitle);
protected abstract JsonSchema generateInterfaceSchema(Class> clazz, Field field);
protected abstract JsonSchema generateInterfaceSchemaWithSelfRef(Class> clazz, Field field, Class> self);
protected abstract JsonSchema generateEnumSchema(Class clazz, Field field);
protected abstract JsonSchema generateMapSchema(Class> clazz, Field field);
protected abstract JsonSchema processSimpleType(Class> clazz, Field field);
protected abstract JsonSchema generateArraySchema(Class> clazz, Field field, String defaultArrayTitle, Class... ifaces);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy