1 package com.atlassian.plugins.rest.doclet.generators.schema;
2
3 import com.atlassian.rest.annotation.RestProperty.Scope;
4
5 import java.util.List;
6 import java.util.Set;
7
8 public class SchemaGenerator {
9 private final Scope scope;
10 private final Set<ModelClass> schemasWithDefinitions;
11 private final ModelClass topLevelModel;
12
13 private SchemaGenerator(final Scope scope, final RichClass topLevelClass) {
14 this.scope = scope;
15 this.topLevelModel = new ModelClass(topLevelClass, null);
16 this.schemasWithDefinitions = topLevelModel.getSchemasReferencedMoreThanOnce(scope);
17 }
18
19 public static Schema generateSchema(RichClass modelClass, Scope scope) {
20 return new SchemaGenerator(scope, modelClass).generateTopLevel();
21 }
22
23 private Schema generateTopLevel() {
24 Schema.Builder topLevelSchema = generate(topLevelModel);
25
26 String title = topLevelModel.getTopLevelTitle();
27 if (title != null) {
28 topLevelSchema.setId("https://docs.atlassian.com/jira/REST/schema/" + Schema.titleToId(title) + "#");
29 topLevelSchema.setTitle(title);
30 }
31
32 for (ModelClass schemaThatNeedsDefinition : schemasWithDefinitions) {
33 topLevelSchema.addDefinition(generate(schemaThatNeedsDefinition).build());
34 }
35
36 return topLevelSchema.build();
37 }
38
39 private Schema generateWithReferencing(ModelClass model) {
40 if (schemasWithDefinitions.contains(model)) {
41 return Schema.ref(model.getTitle());
42 } else {
43 return generate(model).build();
44 }
45 }
46
47 private Schema.Builder generate(final ModelClass model) {
48 final Schema.Builder builder = Schema.builder();
49
50 builder.setType(model.getType());
51 builder.setTitle(model.getTitle());
52 builder.setDescription(model.getDescription());
53
54 if (model.isAbstract()) {
55 List<ModelClass> subModels = model.getSubModels();
56 if (subModels.size() > 0) {
57 for (ModelClass subModel : subModels)
58 {
59 builder.addAnyOf(generateWithReferencing(subModel));
60 }
61 return builder;
62 }
63 }
64
65 model.getPatternedProperties().ifPresent(patternAndModel ->
66 builder.addPatternProperty(patternAndModel.getPattern(), generateWithReferencing(patternAndModel.getValuesType())));
67
68 model.getCollectionItemModel().ifPresent(modelClass ->
69 builder.setItems(generateWithReferencing(modelClass)));
70
71 for (Property property : model.getProperties(scope)) {
72 builder.addProperty(property.name, generateWithReferencing(property.model));
73 if (property.required) {
74 builder.addRequired(property.name);
75 }
76 }
77
78 if (model.getActualClass().isEnum()) {
79 builder.setEnum((Class<Enum>) model.getActualClass());
80 }
81
82 return builder;
83 }
84 }